Skip to content

Conversation

@AdamGrzybkowski
Copy link
Contributor

WOOMOB-1722

Description

We had a small problem on Today/Upcoming tabs. If the booking displayed on one of those tabs would get deleted on the server, we wouldn't reflect that as the Booking would be cached locally and the app wouldn't delete it.

This PR fixes it by making sure that we clear the table from the bookings that were not received in the first page load for both Today and Upcoming tabs.

To do that, I extracted the creation of the Today/Upcoming DateRange filter so that I can create the same one in BookingStore and check if that's the one used. After that, the app will delete all the bookings that match the given DateRange filter and if the Booking ID is not in the newly loaded list. This was done that way to be the least destructive to the Bookings table, so we only clear the entities that are indeed unnecessary (most likely).

Test Steps

  1. Make sure you have some bookings in the Today and Upcoming tabs
  2. Launch the app
  3. Go to Today and load the bookings
  4. Trash one of the booking from the Today tab via the web
  5. Refresh the Today tab in the app
  6. Verify the booking was removed

Images/gif

soft_clear.mp4
  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

With this change when we fetch the initial page with the DateRange filter matching Today or Upcoming range the Bookings table will be cleared
only from the bookings that are not in the initial page load.
@dangermattic
Copy link
Collaborator

1 Warning
⚠️ This PR is assigned to the milestone 23.8. This milestone is due in less than 2 days.
Please make sure to get it merged by then or assign it to a milestone with a later deadline.

Generated by 🚫 Danger

Copilot finished reviewing on behalf of AdamGrzybkowski November 26, 2025 08:42
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 fixes a caching issue where deleted bookings weren't being removed from the local database when fetched from the server. The solution implements selective deletion of cached bookings for Today/Upcoming tabs on the first page load, ensuring stale data is properly cleaned up.

Key changes:

  • Introduced BookingsDateRangePresets to provide canonical date range filters shared across app and data layers
  • Implemented conditional deletion logic in BookingsStore that clears cached bookings matching Today/Upcoming date ranges when fetching page 1
  • Changed BookingFilters parameter from nullable to non-nullable with EMPTY as the default value

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
BookingsDateRangePresets.kt New utility object providing factory methods for today() and upcoming() date range presets with proper UTC handling
BookingsStore.kt Added deletion logic for page 1 fetches with today/upcoming filters, plus isTodayOrUpcoming() helper method
BookingsDao.kt Added deleteForSiteWithDateRangeFilter() query to selectively delete bookings matching date range and excluding specified IDs
BookingListFiltersBuilder.kt Refactored to use shared BookingsDateRangePresets instead of inline date range construction
BookingListHandler.kt Changed filters parameter type from nullable to non-nullable BookingFilters
BookingsRepository.kt Updated filters parameter signature to non-nullable BookingFilters
BookingsStoreTest.kt Added test cases for new deletion behavior scenarios and updated existing tests with Clock dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Nov 26, 2025

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App NameWooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commitc2cf448
Direct Downloadwoocommerce-wear-prototype-build-pr15022-c2cf448.apk

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Nov 26, 2025

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

App NameWooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commitc2cf448
Direct Downloadwoocommerce-prototype-build-pr15022-c2cf448.apk

@codecov-commenter
Copy link

codecov-commenter commented Nov 26, 2025

Codecov Report

❌ Patch coverage is 65.95745% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.57%. Comparing base (e9f11a2) to head (c2cf448).
⚠️ Report is 24 commits behind head on trunk.

Files with missing lines Patch % Lines
...press/android/fluxc/persistence/dao/BookingsDao.kt 0.00% 14 Missing ⚠️
...xc/network/rest/wpcom/wc/bookings/BookingsStore.kt 85.71% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##              trunk   #15022      +/-   ##
============================================
+ Coverage     38.55%   38.57%   +0.02%     
- Complexity    10289    10297       +8     
============================================
  Files          2161     2162       +1     
  Lines        122614   122647      +33     
  Branches      16899    16904       +5     
============================================
+ Hits          47271    47311      +40     
+ Misses        70543    70527      -16     
- Partials       4800     4809       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@irfano irfano self-assigned this Nov 26, 2025
Comment on lines +59 to +61
// Clear existing bookings when fetching the first page.
// If filters are applied, only clear entries that match the applied filters,
// otherwise (no filters) clear all entries for the site.
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment here is not entirely accurate. We say, If filters are applied, only clear entries that match the applied filters, but this is only true for date filters. The issue still exists for other filter types. For example, I filtered “No-show” bookings, trashed one, refreshed the list, and it was still visible.
If we want to address this for all cases, we’ll need to always delete cached entities when any filter is applied. Since it already works for the date filter, we could turn that into a more general solution. WDYT?

Copy link
Contributor Author

@AdamGrzybkowski AdamGrzybkowski Nov 27, 2025

Choose a reason for hiding this comment

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

Since it already works for the date filter, we could turn that into a more general solution. WDYT?

I initially did that, but then I thought that there was a reason why we added this check in the first place, so I decided to strictly add this logic for Today and Upcoming filter.

I'm open to changing that. I wonder if we had similar problems with Products or Orders, and how they were solved there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm thinking about it, I'm not sure we need it. We can only apply other filters in the All tab. This tab, without filters applied, will delete or bookings for a selected site on the initial load. So the problems should be less visible and we won't be clearing the data that we would get on next page loads.

Copy link
Contributor

Choose a reason for hiding this comment

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

True, the issue is less visible for the All tab, but the All filter is saved, and it's possible that the user prefers to always keep a certain filter enabled. In that case, it becomes the same situation as the Today and Upcoming tabs.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm open to changing that. I wonder if we had similar problems with Products or Orders, and how they were solved there?

I've just tested the Products tab, and the issue exists there as well.

Comment on lines 70 to 75
bookingsDao.deleteForSiteWithDateRangeFilter(
site.localId(),
filters.dateRange,
entities.map { it.id.value }
)
bookingsDao.insertOrReplace(entities)
Copy link
Contributor

Choose a reason for hiding this comment

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

There is also an alternative way to handle removed bookings. We can compare the new entities with the cached bookings and detect the removed ones instead of removing all cached data. I know replaceAllForSite() is what we already use, but removing only trashed bookings seems like a better approach to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you clarify? The current implementation only removes the local entities if they are not present in the response from the server. I'm not clearing all cached data here.

Copy link
Contributor

@irfano irfano Nov 27, 2025

Choose a reason for hiding this comment

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

cachedFilteredBookings = [A, B, C]
remoteFilteredBookings = [B, C, D] (A is removed)

// Current implementation
runNewDBTransaction {
    remove(A, B, C)
    insertOrReplace(B, C, D)
}

// My suggestion
runNewDBTransaction {
    remove(A)
    insertOrReplace(B, C, D)
}

In the current implementation, we remove the entire cachedFilteredBookings, right?

This is a minor suggestion and it won’t affect the behavior. It will make the DB work a smaller task, but we’ll still need to find the removed booking (A). Still, I think reducing the number of DB transactions is the better approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the current implementation, we remove the entire cachedFilteredBookings, right?

No. We pass the IDs of the fetched bookings and have this SQL query condition AND ((:idsSize = 0) OR id NOT IN (:ids)) to make sure we only delete the ones that are not in the list. It's exactly as in your suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I missed that in the SQL. Then it’s okay. Thanks!

My last feedback: can we unify deleteForSiteWithDateRangeFilter() and insertOrReplace() into a single DB transaction? Having two separate transactions might trigger additional observations in the view models. I fixed a similar issue before here: #14800.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, this is not a problem, because we are only removing items that should be deleted. The other issue was created because we were deleting and then inserting the same items.

So in a scenario from #14800 the flickering would still occur, because the item will actually be deleted, no matter if it's wrapped in one transaction or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will wrap them in one transaction because it won't hurt us, but this wouldn't trigger the same issue mentioned above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@irfano Fixed in c2cf448

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I noticed it currently doesn’t cause any issues, but it could still lead to a hard-to-diagnose problem in the future. Thanks for making the change. 👍🏻

Copy link
Contributor

@irfano irfano left a comment

Choose a reason for hiding this comment

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

Good job noticing and addressing this issue. LGTM! This fixed the problem for the Today and Upcoming tabs. My two pieces of feedback were:
- Improving the stored cache deletion logic,

  • Fixing the same issue for the All tab as well.

But these can be handled in a separate PR, no need to include them here. Approving! ✅

Copy link
Contributor

@irfano irfano left a comment

Choose a reason for hiding this comment

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

I requested changes again. Please check my last comment about unifying the db transactions.

@irfano irfano merged commit 18f870e into trunk Nov 27, 2025
18 checks passed
@irfano irfano deleted the issue/WOOMOB-1722 branch November 27, 2025 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants