RevenueCat / purchases-android

Android in-app purchases and subscriptions made easy.
https://www.revenuecat.com/
MIT License
253 stars 51 forks source link

PurchaserInfo contains no subscriptions if app was started offline at first start #161

Closed ubuntudroid closed 2 years ago

ubuntudroid commented 4 years ago

library version: 3.2.0

Steps to reproduce:

  1. Install an old version of the app (without RevenueCat integration)
  2. (Test-)purchase a subscription (the entitlement is stored in my app's database)
  3. Install a new version with RevenueCat (update)
  4. Go offline
  5. Start the new version

I've added some handling to the app to make migration for existing users as smooth as possible: If the app is started offline after the user has updated to the new version I use my old entitlement data until RevenueCat SDK reports that it could successfully retrieve PurchaserInfo (either from getPurchaserInfoWith() or onReceived()). As soon as I get a PurchaserInfo I switch over to RevenueCat as the single source of truth and never check my old entitlement data again.

However what I've observed is (continuing from above):

  1. The user is entitled (as per my old entitlement data which is fetched in the error callback of getPurchaserInfoWith()).
  2. Come online.
  3. getPurchaserInfoWith() is executed (I trigger it manually by trying to access a premium feature) and returns a PurchaserInfo(both in the success listener and in onReceived()), but - lo and behold - it is completely empty! So:
  4. The user is not entitled anymore as now I am using RevenueCat as source of truth.
  5. Run getPurchaserInfoWith() again or put the app into background and foreground it again: a filled PurchaserInfo is returned and now:
  6. The user is entitled again.

So the question is: why do I get an empty PurchaserInfo the first time after coming online? This creates a very weird situation where the user has no access to my premium features until the "real" PurchaserInfo arrives. I found no hint, that I could use to discard the first PurchaserInfo unfortunately - it looks perfectly valid other than that the entitlements and subscriptions are empty (as if the user didn't have bought the subscription).

rkotzy commented 4 years ago

Are you manually restoring purchases anywhere to migrate users?

The PurchaserInfo will always read from the cache first (if available) then update the cache through the network in the background. That's what you may be experiencing here, but it's a little unclear at what step do you expect the purchases to be migrated to RevenueCat?

If you determine the user is not subscribed in RevenueCat, but subscribed in your old system, you can programmatically trigger a restore. This will sync the subscription status with RevenueCat, but does require a network connection to complete.

ubuntudroid commented 4 years ago

Currently I don't manually restore purchases (although reading through the discussion forums I figured I might have to).

But the interesting thing is: why is the first PurchaserInfo empty and the second one (even if triggered only a few seconds later) is populated - even without ever calling restoreTransactions()? Why do I even get the first empty one? Everything would be fine, if the first (empty) one wasn't returned by the getPurchaserInfoWith() callback and onReceived(). 🤔

My current plan for a (partial) workaround is: if I detect a discrepancy between RC and my local subscription handling, I trigger a purchase restore and discard the empty PurchaserInfo. This should work as long as I have some local data left from before the update to check against. But it won't work for returning users who just installed the app again and where I can't compare. They will have no access to my premium features until getPurchaserInfoWith() is triggered again when they navigate through the app and stumble on another premium feature.

I hope my explanation makes sense! 😅

jeiting commented 4 years ago

Yeah, unless you manually trigger a restore, our initial purchaser info will be empty since we haven't seen any receipts. Sometimes, we may get a receipt if a renewal happens to have happened in between, but not usually the case. Perhaps more frequent in sandbox.

ubuntudroid commented 4 years ago

Okay, so I will now always trigger a restore regardless of my old subscription state if it is the first start of the app after install/update to a RevenueCat enabled version.

I'll report back in case the empty PurchaseInfo still pops up after a restore because even with the workaround outlined above the second case cannot be circumvented:

it won't work for returning users who just installed the app again and where I can't compare. They will have no access to my premium features until getPurchaserInfoWith() is triggered again when they navigate through the app and stumble on another premium feature.

ubuntudroid commented 4 years ago

@jeiting I've implemented restore as outlined in my last comment. However I still get an empty PurchaseInfo in onReceived() after (according to the log) the SDK correctly fetched the purchase history, but has not yet checked them for entitlements. This happens afterwards as per the log (see below, it's already filtered and only contains relevant lines, grep for onReceived for PurchaseInfo objects returned by onReceived()).

As the log shows the first PurchaseInfo object should not be sent to the listeners until the state of the purchases fetched from history has been verified by the SDK against the backend/Google Play which only happens afterwards.

Thus my idea for a temporary (!) workaround: can we always just safely ignore the first PurchaseInfo coming from the SDK after install / upgrade to a RC enabled version?

Log (right after going online and calling restorePurchasesWith())
Potentially sensitive data has been replaced with placeholders
``` 2020-06-15 19:01:39.023 24701-24854/my.app.id I/(PurchasesRepository.kt:277)restorePurchases(): Restoring purchases... 2020-06-15 19:01:39.023 24701-24854/my.app.id D/[Purchases] - DEBUG: Restoring purchases 2020-06-15 19:01:39.026 24701-24854/my.app.id D/[Purchases] - DEBUG: Querying purchase history for type subs 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_3_month_2 1592238923060 token1 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_12_month_3 1581438186977 token2 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_12_month_2 1580919848501 token3 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_3_month_1 1579184082820 token4 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_1_month_4 1576779193864 token5 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_1_month_3 1570715829773 token6 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_1_month_2 1570694236763 token7 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_1_month_1 1567504666830 token8 2020-06-15 19:01:40.404 24701-24701/my.app.id D/[Purchases] - DEBUG: Querying purchase history for type inapp 2020-06-15 19:01:40.871 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_lifetime_3 1591793184834 token9 2020-06-15 19:01:40.871 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_lifetime_1 1588156418127 token10 2020-06-15 19:01:40.871 24701-24701/my.app.id D/[Purchases] - DEBUG: Purchase history retrieved premium_lifetime_2 1581498049999 token11 2020-06-15 19:01:40.880 24701-24701/my.app.id D/[Purchases] - DEBUG: Found 0 unsynced attributes for appUserID: $RCAnonymousID:userId 2020-06-15 19:01:40.887 24701-24701/my.app.id D/[Purchases] - DEBUG: Found 0 unsynced attributes for appUserID: $RCAnonymousID:userId 2020-06-15 19:01:40.888 24701-24701/my.app.id D/[Purchases] - DEBUG: Found 0 unsynced attributes for appUserID: $RCAnonymousID:userId 2020-06-15 19:01:40.890 24701-24701/my.app.id D/[Purchases] - DEBUG: Found 0 unsynced attributes for appUserID: $RCAnonymousID:userId 2020-06-15 19:01:43.301 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:43.312 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:43.318 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token8 2020-06-15 19:01:43.322 24701-24866/my.app.id D/[Purchases] - DEBUG: Sending latest purchaser info to listener 2020-06-15 19:01:43.324 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token8, purchaseTime=1567504666830, sku=premium_1_month_1, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_1_month_1","purchaseToken":"token8","purchaseTime":1567504666830,"developerPayload":null}, type=SUBS) restored 2020-06-15 19:01:43.340 24701-24701/my.app.id I/(PurchasesRepository.kt:389)onReceived(): Got new purchaser info: 2020-06-15 19:01:43.963 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:43.972 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:43.973 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token7 2020-06-15 19:01:43.975 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token7, purchaseTime=1570694236763, sku=premium_1_month_2, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_1_month_2","purchaseToken":"token7","purchaseTime":1570694236763,"developerPayload":null}, type=SUBS) restored 2020-06-15 19:01:44.262 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:44.381 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:44.554 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:44.557 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:44.558 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token6 2020-06-15 19:01:44.561 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token6, purchaseTime=1570715829773, sku=premium_1_month_3, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_1_month_3","purchaseToken":"token6","purchaseTime":1570715829773,"developerPayload":null}, type=SUBS) restored 2020-06-15 19:01:45.210 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:45.217 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:45.219 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token5 2020-06-15 19:01:45.221 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token5, purchaseTime=1576779193864, sku=premium_1_month_4, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_1_month_4","purchaseTime":1576779193864,"purchaseToken":"token5"}, type=SUBS) restored 2020-06-15 19:01:45.318 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:45.925 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:45.931 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:45.932 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token4 2020-06-15 19:01:45.935 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token4, purchaseTime=1579184082820, sku=premium_3_month_1, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_3_month_1","purchaseToken":"token4","purchaseTime":1579184082820,"developerPayload":null}, type=SUBS) restored 2020-06-15 19:01:45.965 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:46.535 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:46.538 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:46.539 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token3 2020-06-15 19:01:46.540 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token3, purchaseTime=1580919848501, sku=premium_12_month_2, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_12_month_2","purchaseTime":1580919848501,"purchaseToken":"token3"}, type=SUBS) restored 2020-06-15 19:01:46.663 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:47.155 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:47.160 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:47.162 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token2 2020-06-15 19:01:47.163 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token2, purchaseTime=1581438186977, sku=premium_12_month_3, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_12_month_3","purchaseToken":"token2","purchaseTime":1581438186977,"developerPayload":null}, type=SUBS) restored 2020-06-15 19:01:47.285 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:47.992 24701-24701/my.app.id D/[Purchases] - DEBUG: Error acknowledging purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: DEVELOPER_ERROR. 2020-06-15 19:01:48.382 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:48.392 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:48.399 24701-24866/my.app.id D/[Purchases] - DEBUG: Consuming purchase with token token11 2020-06-15 19:01:48.402 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchaser info updated, sending to listener 2020-06-15 19:01:48.402 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=true, purchaseToken=token11, purchaseTime=1581498049999, sku=premium_lifetime_2, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_lifetime_2","purchaseTime":1581498049999,"purchaseToken":"token11"}, type=INAPP) restored 2020-06-15 19:01:48.404 24701-24701/my.app.id I/(PurchasesRepository.kt:389)onReceived(): Got new purchaser info: 2020-06-15 19:01:48.830 24701-24701/my.app.id D/[Purchases] - DEBUG: Error consuming purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: ITEM_NOT_OWNED. 2020-06-15 19:01:49.713 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:49.729 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:49.733 24701-24866/my.app.id D/[Purchases] - DEBUG: Consuming purchase with token token10 2020-06-15 19:01:49.735 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchaser info updated, sending to listener 2020-06-15 19:01:49.735 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=true, purchaseToken=token10, purchaseTime=1588156418127, sku=premium_lifetime_1, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_lifetime_1","purchaseTime":1588156418127,"purchaseToken":"token10"}, type=INAPP) restored 2020-06-15 19:01:49.737 24701-24701/my.app.id I/(PurchasesRepository.kt:389)onReceived(): Got new purchaser info: 2020-06-15 19:01:50.026 24701-24701/my.app.id D/[Purchases] - DEBUG: Error consuming purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: ITEM_NOT_OWNED. 2020-06-15 19:01:50.981 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:50.985 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:50.987 24701-24866/my.app.id D/[Purchases] - DEBUG: Consuming purchase with token token9 2020-06-15 19:01:50.989 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchaser info updated, sending to listener 2020-06-15 19:01:50.989 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=true, purchaseToken=token9, purchaseTime=1591793184834, sku=premium_lifetime_3, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_lifetime_3","purchaseToken":"token9","purchaseTime":1591793184834,"developerPayload":null}, type=INAPP) restored 2020-06-15 19:01:50.990 24701-24701/my.app.id I/(PurchasesRepository.kt:389)onReceived(): Got new purchaser info: 2020-06-15 19:01:51.303 24701-24701/my.app.id D/[Purchases] - DEBUG: Error consuming purchase. Will retry next queryPurchases. DebugMessage: Item is not owned by the user.. ErrorCode: ITEM_NOT_OWNED. 2020-06-15 19:01:51.848 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 2020-06-15 19:01:51.859 24701-24866/my.app.id D/[Purchases] - DEBUG: POST /receipts 200 2020-06-15 19:01:51.867 24701-24866/my.app.id D/[Purchases] - DEBUG: Acknowledging purchase with token token1 2020-06-15 19:01:51.871 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchaser info updated, sending to listener 2020-06-15 19:01:51.871 24701-24866/my.app.id D/[Purchases] - DEBUG: Purchase PurchaseHistoryRecordWrapper(isConsumable=false, purchaseToken=token1, purchaseTime=1592238923060, sku=premium_3_month_2, purchaseHistoryRecord=PurchaseHistoryRecord. Json: {"productId":"premium_3_month_2","purchaseToken":"token1","purchaseTime":1592238923060,"developerPayload":null}, type=SUBS) restored 2020-06-15 19:01:51.874 24701-24701/my.app.id I/(PurchasesRepository.kt:389)onReceived(): Got new purchaser info: 2020-06-15 19:01:52.640 24701-24701/my.app.id D/[Purchases] - DEBUG: [QueryPurchases] Saving token token1 with hash someHash 2020-06-15 19:01:52.640 24701-24701/my.app.id D/[Purchases] - DEBUG: [QueryPurchases] Tokens already posted: [] 2020-06-15 19:01:52.640 24701-24701/my.app.id D/[Purchases] - DEBUG: [QueryPurchases] Tokens in cache before saving [] 2020-06-15 19:01:52.640 24701-24701/my.app.id D/[Purchases] - DEBUG: [QueryPurchases] Saving tokens [someHash] ```
ubuntudroid commented 4 years ago

@jeiting @rkotzy any insights? Is the workaround outlined in my previous post a valid one?

I unfortunately can't ship without this fixed as I will face a whole lot of (rightly) angry users if I don't handle this properly: in my app certain settings are automatically disabled when the user is not entitled to premium anymore - and they are not automatically reenabled later when they are entitled again because those are opt-in settings. 💥 🤷 And I don't really want to work around that setting handling part because in the regular (non-restore) case the current handling provides the best user experience.

aboedo commented 4 years ago

reopening for discussion, sorry I'd missed this ticket. This is a valid use case, we've been discussing it here as well.

assuming that the first purchaserInfo you get might be outdated will work, with some caveats:

In the future, we'll have to come up with a better system and API to aid in these cases. See the discussion in the attached issue.

ubuntudroid commented 4 years ago

Thanks for the update! 🙏 Sorry for missing that other ticket, thought I had thoroughly searched the other issues for similar ones, but apparently I didn't. 😓

Dropping the very first PurchaserInfo unfortunately proved too flaky as there were several edge cases (mostly due to threading) which made this unnecessarily complicated. I now worked around the issue by not toggling premium features off right away when a missing entitlement is detected (as it is the case for the empty first PurchaserInfo object), but instead just guard their getters with a premium check, so the next time they are checked they will be reported as off. In most cases this will enough to make the migration transparent for our users.

Looking forward to the changes in the SDK - I'll stay subscribed to this issue. Guess it will be closed once the changes are shipped? Or is there some other place I should monitor to follow progress?

rkotzy commented 4 years ago

I know this is an old issue, but want to check in to make sure we understand the problem and if there's a current workaround. Is the problem with the onReceived() in the UpdatedPurchaserInfoListener or the restorePurchases ReceivePurchaserInfoListener?

The restorePurchases call should not return a PurchaserInfo from the cache and always have the latest entitlement status.

ubuntudroid commented 4 years ago

@rkotzy The problem is with onReceived(). I've outlined our workaround in https://github.com/RevenueCat/purchases-android/issues/161#issuecomment-646699852 . It seems to work fine so far as long I maintain a somewhat lenient approach to removing access to premium features.

taquitos commented 3 years ago

Tracking internally https://app.shortcut.com/revenuecat/story/9980/add-configuration-option-for-getcustomerinfo

taquitos commented 2 years ago

@ubuntudroid I don't know if you've seen it, but we added a cache policy object that allows you to configure the behavior now! https://github.com/RevenueCat/purchases-android/pull/546 I'm going to close this issue, but definitely feel free to open another if needed! Thank you for your patience, I know this is an older issue 😄

mdmota commented 2 years ago

I don't know if it has anything to do with the discussion. I have a problem with the following flow. My app needs login to be a subscriber. After logging in and subscribe everything works normally. If I clear the app's cache and open it again and sign in, PurchaserInfo doesn't come with active subscriptions. If I uninstall and reinstall the app, I log in also does not come with active subscriptions. Any clues?

aboedo commented 2 years ago

@mdmota I replied on the other ticket, let's keep the conversation in that one 👍

mdmota commented 2 years ago

ok , i

Em sex., 26 de ago. de 2022 às 18:57, Andy Boedo @.***> escreveu:

@mdmota https://github.com/mdmota I replied on the other ticket, let's keep the conversation in that one 👍

— Reply to this email directly, view it on GitHub https://github.com/RevenueCat/purchases-android/issues/161#issuecomment-1228994880, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFCH45LLCH76MTTCQ6TU3VLV3E4SXANCNFSM4N2WG7LA . You are receiving this because you were mentioned.Message ID: @.***>