Skip to content

Commit 83f3c17

Browse files
authored
Merge pull request #14703 from woocommerce/woomob-1428-woo-possurveys-show-potential-push-notification-after-order
[WOOMOB-1428][Woo POS][Surveys] Show potential user push notification after order creation
2 parents 175bf34 + f2ce531 commit 83f3c17

File tree

5 files changed

+221
-0
lines changed

5 files changed

+221
-0
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/creation/OrderCreateEditViewModel.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ import com.woocommerce.android.ui.products.inventory.FetchProductByIdentifier
145145
import com.woocommerce.android.ui.products.selector.ProductSelectorViewModel.SelectedItem
146146
import com.woocommerce.android.ui.products.selector.ProductSelectorViewModel.SelectedItem.Product
147147
import com.woocommerce.android.ui.products.selector.variationIds
148+
import com.woocommerce.android.ui.woopos.common.util.WooPosSurveysNotificationSchedular
148149
import com.woocommerce.android.util.CoroutineDispatchers
149150
import com.woocommerce.android.util.DateUtils
150151
import com.woocommerce.android.viewmodel.LiveDataDelegate
@@ -210,6 +211,7 @@ class OrderCreateEditViewModel @Inject constructor(
210211
private val totalsHelper: OrderCreateEditTotalsHelper,
211212
private val feedbackRepository: FeedbackRepository,
212213
private val fetchProductByIdentifier: FetchProductByIdentifier,
214+
private val wooPosSurveysNotificationSchedular: WooPosSurveysNotificationSchedular,
213215
dateUtils: DateUtils,
214216
autoSyncOrder: AutoSyncOrder,
215217
autoSyncPriceModifier: AutoSyncPriceModifier,
@@ -1381,6 +1383,7 @@ class OrderCreateEditViewModel @Inject constructor(
13811383
).fold(
13821384
onSuccess = {
13831385
trackOrderCreationSuccess()
1386+
wooPosSurveysNotificationSchedular.schedularPotentialUserSurveyNotification()
13841387
onSuccess(it)
13851388
},
13861389
onFailure = {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.woocommerce.android.ui.woopos.common.util
2+
3+
import com.woocommerce.android.AppPrefsWrapper
4+
import com.woocommerce.android.notifications.local.LocalNotification
5+
import com.woocommerce.android.notifications.local.LocalNotificationScheduler
6+
import com.woocommerce.android.tools.SelectedSite
7+
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
8+
import com.woocommerce.android.util.FeatureFlag
9+
import kotlinx.coroutines.flow.first
10+
import org.wordpress.android.fluxc.store.WooCommerceStore
11+
import javax.inject.Inject
12+
13+
class WooPosSurveysNotificationSchedular @Inject constructor(
14+
private val localNotificationScheduler: LocalNotificationScheduler,
15+
private val appPrefs: AppPrefsWrapper,
16+
private val wooPosPreferencesRepository: WooPosPreferencesRepository,
17+
private val selectedSite: SelectedSite,
18+
private val wooCommerceStore: WooCommerceStore,
19+
) {
20+
companion object {
21+
private val ALLOWED_COUNTRIES = setOf("us", "gb")
22+
}
23+
24+
suspend fun schedularPotentialUserSurveyNotification() {
25+
if (!appPrefs.isWooPosSurveyNotificationPotentialUserShown && areNotificationsAllowed()) {
26+
localNotificationScheduler.scheduleNotification(
27+
LocalNotification.WooPosSurveyPotentialUserNotification(
28+
siteId = selectedSite.get().siteId
29+
)
30+
)
31+
}
32+
}
33+
34+
private suspend fun areNotificationsAllowed(): Boolean =
35+
isAllowedCountry() &&
36+
!wooPosPreferencesRepository.wasOpenedOnce.first() &&
37+
FeatureFlag.WOO_POS_SURVEYS.isEnabled()
38+
39+
private suspend fun isAllowedCountry(): Boolean {
40+
val countryCode = wooCommerceStore.getSiteSettingsAsync(selectedSite.get())?.countryCode
41+
return countryCode?.lowercase() in ALLOWED_COUNTRIES
42+
}
43+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ enum class FeatureFlag {
1010
WC_SHIPPING_BANNER,
1111
BETTER_CUSTOMER_SEARCH_M2,
1212
ORDER_CREATION_AUTO_TAX_RATE,
13+
WOO_POS_SURVEYS,
1314
WOO_POS_HISTORICAL_ORDERS_M1,
1415
WOO_POS_LOCAL_CATALOG_M1,
1516
BOOKINGS_MVP;
@@ -22,6 +23,7 @@ enum class FeatureFlag {
2223

2324
WOO_POS_HISTORICAL_ORDERS_M1,
2425
WC_SHIPPING_BANNER,
26+
WOO_POS_SURVEYS,
2527
BETTER_CUSTOMER_SEARCH_M2,
2628
ORDER_CREATION_AUTO_TAX_RATE,
2729
WOO_POS_LOCAL_CATALOG_M1,

WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/creation/UnifiedOrderEditViewModelTest.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import com.woocommerce.android.ui.products.ProductType
5050
import com.woocommerce.android.ui.products.inventory.FetchProductByIdentifier
5151
import com.woocommerce.android.ui.products.models.SiteParameters
5252
import com.woocommerce.android.ui.products.selector.ProductSelectorViewModel
53+
import com.woocommerce.android.ui.woopos.common.util.WooPosSurveysNotificationSchedular
5354
import com.woocommerce.android.util.captureValues
5455
import com.woocommerce.android.viewmodel.BaseUnitTest
5556
import com.woocommerce.android.viewmodel.ResourceProvider
@@ -106,6 +107,7 @@ abstract class UnifiedOrderEditViewModelTest : BaseUnitTest() {
106107
private lateinit var getShippingMethodsWithOtherValue: GetShippingMethodsWithOtherValue
107108
protected lateinit var feedbackRepository: FeedbackRepository
108109
protected lateinit var fetchProductByIdentifier: FetchProductByIdentifier
110+
private lateinit var wooPosSurveysNotificationSchedular: WooPosSurveysNotificationSchedular
109111

110112
protected val defaultOrderValue = Order.getEmptyOrder(Date(), Date()).copy(id = 123)
111113

@@ -219,6 +221,7 @@ abstract class UnifiedOrderEditViewModelTest : BaseUnitTest() {
219221
)
220222
}
221223
fetchProductByIdentifier = mock()
224+
wooPosSurveysNotificationSchedular = mock()
222225
}
223226

224227
protected abstract val tracksFlow: String
@@ -2175,6 +2178,7 @@ abstract class UnifiedOrderEditViewModelTest : BaseUnitTest() {
21752178
getShippingMethodsWithOtherValue = getShippingMethodsWithOtherValue,
21762179
feedbackRepository = feedbackRepository,
21772180
fetchProductByIdentifier = fetchProductByIdentifier,
2181+
wooPosSurveysNotificationSchedular = wooPosSurveysNotificationSchedular,
21782182
)
21792183
}
21802184

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.woocommerce.android.ui.woopos.common.util
2+
3+
import com.woocommerce.android.AppPrefsWrapper
4+
import com.woocommerce.android.notifications.local.LocalNotification
5+
import com.woocommerce.android.notifications.local.LocalNotificationScheduler
6+
import com.woocommerce.android.tools.SelectedSite
7+
import com.woocommerce.android.ui.woopos.util.WooPosCoroutineTestRule
8+
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
9+
import kotlinx.coroutines.ExperimentalCoroutinesApi
10+
import kotlinx.coroutines.flow.flowOf
11+
import kotlinx.coroutines.test.runTest
12+
import org.junit.Before
13+
import org.junit.Rule
14+
import org.junit.Test
15+
import org.mockito.kotlin.any
16+
import org.mockito.kotlin.mock
17+
import org.mockito.kotlin.never
18+
import org.mockito.kotlin.verify
19+
import org.mockito.kotlin.whenever
20+
import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId
21+
import org.wordpress.android.fluxc.model.SiteModel
22+
import org.wordpress.android.fluxc.store.WooCommerceStore
23+
import org.wordpress.android.fluxc.wc.settings.WCSettingsTestUtils
24+
25+
@ExperimentalCoroutinesApi
26+
class WooPosSurveysNotificationSchedularTest {
27+
@Rule
28+
@JvmField
29+
val coroutinesTestRule = WooPosCoroutineTestRule()
30+
31+
private lateinit var localNotificationScheduler: LocalNotificationScheduler
32+
private lateinit var appPrefs: AppPrefsWrapper
33+
private lateinit var wooPosPreferencesRepository: WooPosPreferencesRepository
34+
private lateinit var selectedSite: SelectedSite
35+
private lateinit var wooCommerceStore: WooCommerceStore
36+
private lateinit var schedular: WooPosSurveysNotificationSchedular
37+
private lateinit var siteModel: SiteModel
38+
39+
@Before
40+
fun setUp() {
41+
localNotificationScheduler = mock()
42+
appPrefs = mock()
43+
wooPosPreferencesRepository = mock()
44+
selectedSite = mock()
45+
wooCommerceStore = mock()
46+
siteModel = mock {
47+
on { siteId }.thenReturn(123L)
48+
}
49+
50+
whenever(selectedSite.get()).thenReturn(siteModel)
51+
52+
schedular = WooPosSurveysNotificationSchedular(
53+
localNotificationScheduler = localNotificationScheduler,
54+
appPrefs = appPrefs,
55+
wooPosPreferencesRepository = wooPosPreferencesRepository,
56+
selectedSite = selectedSite,
57+
wooCommerceStore = wooCommerceStore
58+
)
59+
}
60+
61+
@Test
62+
fun `given all conditions met, when schedularPotentialUserSurveyNotification called, then notification scheduled`() =
63+
runTest {
64+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "US")
65+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
66+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
67+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
68+
69+
schedular.schedularPotentialUserSurveyNotification()
70+
71+
verify(localNotificationScheduler).scheduleNotification(
72+
LocalNotification.WooPosSurveyPotentialUserNotification(siteId = 123L)
73+
)
74+
}
75+
76+
@Test
77+
fun `given notification already shown, when schedularPotentialUserSurveyNotification called, then notification not scheduled`() =
78+
runTest {
79+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "US")
80+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(true)
81+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
82+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
83+
84+
schedular.schedularPotentialUserSurveyNotification()
85+
86+
verify(localNotificationScheduler, never()).scheduleNotification(any())
87+
}
88+
89+
@Test
90+
fun `given country not allowed, when schedularPotentialUserSurveyNotification called, then notification not scheduled`() =
91+
runTest {
92+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "FR")
93+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
94+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
95+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
96+
97+
schedular.schedularPotentialUserSurveyNotification()
98+
99+
verify(localNotificationScheduler, never()).scheduleNotification(any())
100+
}
101+
102+
@Test
103+
fun `given WooPOS opened before, when schedularPotentialUserSurveyNotification called, then notification not scheduled`() =
104+
runTest {
105+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "US")
106+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
107+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(true))
108+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
109+
110+
schedular.schedularPotentialUserSurveyNotification()
111+
112+
verify(localNotificationScheduler, never()).scheduleNotification(any())
113+
}
114+
115+
@Test
116+
fun `given GB country code, when schedularPotentialUserSurveyNotification called, then notification scheduled`() =
117+
runTest {
118+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "GB")
119+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
120+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
121+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
122+
123+
schedular.schedularPotentialUserSurveyNotification()
124+
125+
verify(localNotificationScheduler).scheduleNotification(
126+
LocalNotification.WooPosSurveyPotentialUserNotification(siteId = 123L)
127+
)
128+
}
129+
130+
@Test
131+
fun `given lowercase country code, when schedularPotentialUserSurveyNotification called, then notification scheduled`() =
132+
runTest {
133+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "us")
134+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
135+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
136+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
137+
138+
schedular.schedularPotentialUserSurveyNotification()
139+
140+
verify(localNotificationScheduler).scheduleNotification(
141+
LocalNotification.WooPosSurveyPotentialUserNotification(siteId = 123L)
142+
)
143+
}
144+
145+
@Test
146+
fun `given null country code, when schedularPotentialUserSurveyNotification called, then notification not scheduled`() =
147+
runTest {
148+
val siteSettings = WCSettingsTestUtils.generateSettings(LocalId(1)).copy(countryCode = "")
149+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
150+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
151+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(siteSettings)
152+
153+
schedular.schedularPotentialUserSurveyNotification()
154+
155+
verify(localNotificationScheduler, never()).scheduleNotification(any())
156+
}
157+
158+
@Test
159+
fun `given null site settings, when schedularPotentialUserSurveyNotification called, then notification not scheduled`() =
160+
runTest {
161+
whenever(appPrefs.isWooPosSurveyNotificationPotentialUserShown).thenReturn(false)
162+
whenever(wooPosPreferencesRepository.wasOpenedOnce).thenReturn(flowOf(false))
163+
whenever(wooCommerceStore.getSiteSettingsAsync(siteModel)).thenReturn(null)
164+
165+
schedular.schedularPotentialUserSurveyNotification()
166+
167+
verify(localNotificationScheduler, never()).scheduleNotification(any())
168+
}
169+
}

0 commit comments

Comments
 (0)