Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c48338b
Add barcode icon into the order listing toolbar
AnirudhBhat May 18, 2023
ca53d0d
Modify the navigation graphs to take in additional SKU parameter
AnirudhBhat May 18, 2023
1e889c8
Integrate CodeScanner into OrderListViewModel.kt
AnirudhBhat May 18, 2023
a88ecd3
Pass the SKU parameter into the Order creation screen. Add logic to s…
AnirudhBhat May 18, 2023
fd186f3
Move the fetchProductBySKU call when barcode navargs is present into …
AnirudhBhat May 18, 2023
3f595c9
Move the fetchProductBySKU call when barcode navargs is present into …
AnirudhBhat May 18, 2023
0fa2aad
Rename "barcode" parameter in the navigation graphs to "sku" for bett…
AnirudhBhat May 18, 2023
305556d
Pass sku as argument
AnirudhBhat May 18, 2023
2a9b6a6
Add test to verify proper event is triggered when the code scan succe…
AnirudhBhat May 18, 2023
c425741
implement the abstract variables
AnirudhBhat May 18, 2023
61ce0be
Add test to verify that the event with proper sku is triggered when t…
AnirudhBhat May 18, 2023
c61a8b4
Add test to verify that the search products call is done when view mo…
AnirudhBhat May 18, 2023
0b17e46
Add test to verify that the search products call is not done when vie…
AnirudhBhat May 18, 2023
8a64cae
Fix detekt errors
AnirudhBhat May 18, 2023
84c3b75
Merge branch 'issue/8941-code-scanner-order-creation-ui' into issue/9…
AnirudhBhat May 19, 2023
5404b47
Merge branch 'issue/8944-order-creation-search-product-by-sku' into i…
AnirudhBhat May 19, 2023
fdab607
Fix failing tests
AnirudhBhat May 19, 2023
9d77cb5
Fix failing tests
AnirudhBhat May 19, 2023
cc33983
Move tests related to creation into its respective file
AnirudhBhat May 19, 2023
d66a0d4
Remove unused imports
AnirudhBhat May 22, 2023
debe810
Add barcode setting visibility logic in the order listing screen.
AnirudhBhat May 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,8 @@ class MainActivity :
binding.bottomNav.currentPosition = ORDERS
binding.bottomNav.active(ORDERS.position)
val action = OrderListFragmentDirections.actionOrderListFragmentToOrderCreationFragment(
OrderCreateEditViewModel.Mode.Creation
OrderCreateEditViewModel.Mode.Creation,
null
)
navController.navigateSafely(action)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ class OrderNavigator @Inject constructor() {
is EditOrder -> {
OrderDetailFragmentDirections
.actionOrderDetailFragmentToOrderCreationFragment(
OrderCreateEditViewModel.Mode.Edit(target.orderId)
OrderCreateEditViewModel.Mode.Edit(target.orderId),
null
).let { fragment.findNavController().navigateSafely(it) }
}
is ViewCustomFields -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import com.woocommerce.android.analytics.AnalyticsTracker.Companion.OrderNoteTyp
import com.woocommerce.android.analytics.AnalyticsTracker.Companion.VALUE_FLOW_CREATION
import com.woocommerce.android.analytics.AnalyticsTracker.Companion.VALUE_FLOW_EDITING
import com.woocommerce.android.analytics.AnalyticsTrackerWrapper
import com.woocommerce.android.extensions.isNotNullOrEmpty
import com.woocommerce.android.extensions.runWithContext
import com.woocommerce.android.model.Address
import com.woocommerce.android.model.Order
Expand Down Expand Up @@ -172,6 +173,11 @@ class OrderCreateEditViewModel @Inject constructor(
)
}
monitorOrderChanges()
// Presence of barcode indicates that this screen was called from the
// Order listing screen after scanning the barcode.
if (args.sku.isNotNullOrEmpty()) {
fetchProductBySKU(args.sku!!)
}
}
is Mode.Edit -> {
viewModelScope.launch {
Expand All @@ -189,7 +195,6 @@ class OrderCreateEditViewModel @Inject constructor(
}
}
}

fun onCustomerNoteEdited(newNote: String) {
_orderDraft.value.let { order ->
tracker.track(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import com.woocommerce.android.ui.jitm.JitmFragment
import com.woocommerce.android.ui.main.MainActivity
import com.woocommerce.android.ui.main.MainNavigationRouter
import com.woocommerce.android.ui.orders.OrderStatusUpdateSource
import com.woocommerce.android.ui.orders.creation.IsAddProductViaBarcodeScanningEnabled
import com.woocommerce.android.ui.orders.creation.OrderCreateEditViewModel
import com.woocommerce.android.ui.orders.list.OrderListViewModel.OrderListEvent.ShowErrorSnack
import com.woocommerce.android.ui.orders.list.OrderListViewModel.OrderListEvent.ShowOrderFilters
Expand Down Expand Up @@ -87,6 +88,8 @@ class OrderListFragment :
internal lateinit var currencyFormatter: CurrencyFormatter
@Inject
lateinit var feedbackPrefs: FeedbackPrefs
@Inject
lateinit var isAddProductViaBarcodeScanningEnabled: IsAddProductViaBarcodeScanningEnabled

private val viewModel: OrderListViewModel by viewModels()
private var snackBar: Snackbar? = null
Expand Down Expand Up @@ -144,6 +147,9 @@ class OrderListFragment :

orderListMenu = menu
searchMenuItem = menu.findItem(R.id.menu_search)
// TODO Remove the barcode setting visibility logic after the feature is in production.
val barcodeOption = menu.findItem(R.id.menu_barcode)
barcodeOption.isVisible = isAddProductViaBarcodeScanningEnabled()
searchView = searchMenuItem?.actionView as SearchView?
searchView?.queryHint = getSearchQueryHint()
}
Expand Down Expand Up @@ -256,6 +262,10 @@ class OrderListFragment :
enableSearchListeners()
true
}
R.id.menu_barcode -> {
viewModel.startScan()
true
}
else -> false
}
}
Expand Down Expand Up @@ -349,6 +359,9 @@ class OrderListFragment :
is OrderListViewModel.OrderListEvent.ShowIPPDismissConfirmationDialog -> {
showIPPFeedbackDismissConfirmationDialog()
}
is OrderListViewModel.OrderListEvent.OnBarcodeScanned -> {
openOrderCreationFragment(event.code)
}
else -> event.isHandled = false
}
}
Expand Down Expand Up @@ -451,12 +464,13 @@ class OrderListFragment :
findNavController().navigateSafely(R.id.action_orderListFragment_to_orderFilterListFragment)
}

private fun openOrderCreationFragment() {
private fun openOrderCreationFragment(code: String? = null) {
OrderDurationRecorder.startRecording()
AnalyticsTracker.track(AnalyticsEvent.ORDERS_ADD_NEW)
findNavController().navigateSafely(
OrderListFragmentDirections.actionOrderListFragmentToOrderCreationFragment(
OrderCreateEditViewModel.Mode.Creation
OrderCreateEditViewModel.Mode.Creation,
code
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import com.woocommerce.android.notifications.NotificationChannelType
import com.woocommerce.android.tools.NetworkStatus
import com.woocommerce.android.tools.SelectedSite
import com.woocommerce.android.ui.orders.OrderStatusUpdateSource
import com.woocommerce.android.ui.orders.creation.CodeScanner
import com.woocommerce.android.ui.orders.creation.CodeScannerStatus
import com.woocommerce.android.ui.orders.details.OrderDetailRepository
import com.woocommerce.android.ui.orders.filters.domain.GetSelectedOrderFiltersCount
import com.woocommerce.android.ui.orders.filters.domain.GetWCOrderListDescriptorWithFilters
Expand Down Expand Up @@ -105,6 +107,7 @@ class OrderListViewModel @Inject constructor(
private val analyticsTracker: AnalyticsTrackerWrapper,
private val appPrefs: AppPrefs,
private val feedbackPrefs: FeedbackPrefs,
private val codeScanner: CodeScanner,
) : ScopedViewModel(savedState), LifecycleOwner {
private val lifecycleRegistry: LifecycleRegistry by lazy {
LifecycleRegistry(this)
Expand Down Expand Up @@ -279,6 +282,21 @@ class OrderListViewModel @Inject constructor(
}
}

fun startScan() {
launch {
codeScanner.startScan().collect { status ->
when (status) {
is CodeScannerStatus.Failure -> {
// TODO handle failure case
}
is CodeScannerStatus.Success -> {
triggerEvent(OrderListEvent.OnBarcodeScanned(status.code))
}
}
}
}
}

/**
* Track user clicked to open an order and the status of that order, along with some
* data about the order custom fields
Expand Down Expand Up @@ -718,6 +736,8 @@ class OrderListViewModel @Inject constructor(
object ShowIPPDismissConfirmationDialog : OrderListEvent()

data class OpenIPPFeedbackSurveyLink(val url: String) : OrderListEvent()

data class OnBarcodeScanned(val code: String) : OrderListEvent()
}

@Parcelize
Expand Down
5 changes: 5 additions & 0 deletions WooCommerce/src/main/res/menu/menu_order_list_fragment.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_barcode"
android:icon="@drawable/ic_barcode"
android:title="@string/scan_barcode"
app:showAsAction="always" />
<item
android:id="@+id/menu_search"
android:icon="@drawable/ic_search_24dp"
Expand Down
4 changes: 4 additions & 0 deletions WooCommerce/src/main/res/navigation/nav_graph_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@
<argument
android:name="mode"
app:argType="com.woocommerce.android.ui.orders.creation.OrderCreateEditViewModel$Mode" />
<argument
android:name="sku"
app:argType="string"
app:nullable="true"/>
</action>
</fragment>
<fragment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@
<argument
android:name="mode"
app:argType="com.woocommerce.android.ui.orders.creation.OrderCreateEditViewModel$Mode" />
<argument
android:name="sku"
app:argType="string"
app:nullable="true"/>
</fragment>
<dialog
android:id="@+id/orderStatusSelectorDialog"
Expand Down
4 changes: 4 additions & 0 deletions WooCommerce/src/main/res/navigation/nav_graph_orders.xml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@
<argument
android:name="mode"
app:argType="com.woocommerce.android.ui.orders.creation.OrderCreateEditViewModel$Mode" />
<argument
android:name="sku"
app:argType="string"
app:nullable="true"/>
</action>

<action
Expand Down
1 change: 1 addition & 0 deletions WooCommerce/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
<string name="emdash" translatable="false">\u2014</string>
<string name="share">Share</string>
<string name="search">Search</string>
<string name="scan_barcode">Scan Barcode</string>
<string name="clear">Clear</string>
<string name="done">Done</string>
<string name="back">Back</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import com.woocommerce.android.model.RequestResult
import com.woocommerce.android.notifications.NotificationChannelType
import com.woocommerce.android.tools.NetworkStatus
import com.woocommerce.android.tools.SelectedSite
import com.woocommerce.android.ui.orders.creation.CodeScanner
import com.woocommerce.android.ui.orders.creation.CodeScannerStatus
import com.woocommerce.android.ui.orders.details.OrderDetailRepository
import com.woocommerce.android.ui.orders.filters.domain.GetSelectedOrderFiltersCount
import com.woocommerce.android.ui.orders.filters.domain.GetWCOrderListDescriptorWithFilters
Expand Down Expand Up @@ -98,6 +100,7 @@ class OrderListViewModelTest : BaseUnitTest() {
private val analyticsTracker: AnalyticsTrackerWrapper = mock()
private val appPrefs = mock<AppPrefs>()
private val feedbackPrefs = mock<FeedbackPrefs>()
private val codeScanner = mock<CodeScanner>()

@Before
fun setup() = testBlocking {
Expand Down Expand Up @@ -148,6 +151,7 @@ class OrderListViewModelTest : BaseUnitTest() {
analyticsTracker = analyticsTracker,
appPrefs = appPrefs,
feedbackPrefs = feedbackPrefs,
codeScanner = codeScanner,
)

@Test
Expand Down Expand Up @@ -954,6 +958,38 @@ class OrderListViewModelTest : BaseUnitTest() {
assertEquals(IPPSurveyFeedbackBannerState.Hidden, viewModel.viewState.ippFeedbackBannerState)
}

// region barcode scanner

@Test
fun `when code scanner succeeds, then trigger proper event`() {
whenever(codeScanner.startScan()).thenAnswer {
flow<CodeScannerStatus> {
emit(CodeScannerStatus.Success("12345"))
}
}

viewModel = createViewModel()
viewModel.startScan()

assertThat(viewModel.event.value).isInstanceOf(OrderListViewModel.OrderListEvent.OnBarcodeScanned::class.java)
}

@Test
fun `when code scanner succeeds, then trigger event with proper sku`() {
whenever(codeScanner.startScan()).thenAnswer {
flow<CodeScannerStatus> {
emit(CodeScannerStatus.Success("12345"))
}
}

viewModel = createViewModel()
viewModel.startScan()

assertThat(viewModel.event.value).isEqualTo(OrderListViewModel.OrderListEvent.OnBarcodeScanned("12345"))
}

//endregion

private companion object {
const val ANY_SEARCH_QUERY = "search query"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.woocommerce.android.R
import com.woocommerce.android.analytics.AnalyticsEvent
import com.woocommerce.android.analytics.AnalyticsTracker
import com.woocommerce.android.analytics.AnalyticsTracker.Companion.VALUE_FLOW_CREATION
import com.woocommerce.android.initSavedStateHandle
import com.woocommerce.android.model.Address
import com.woocommerce.android.model.Order
import com.woocommerce.android.ui.orders.OrderNavigationTarget.ViewOrderStatusSelector
Expand All @@ -21,6 +22,7 @@ import com.woocommerce.android.ui.orders.creation.navigation.OrderCreateEditNavi
import com.woocommerce.android.ui.orders.creation.navigation.OrderCreateEditNavigationTarget.SelectItems
import com.woocommerce.android.ui.orders.creation.navigation.OrderCreateEditNavigationTarget.ShowCreatedOrder
import com.woocommerce.android.ui.orders.creation.navigation.OrderCreateEditNavigationTarget.ShowProductDetails
import com.woocommerce.android.ui.products.models.SiteParameters
import com.woocommerce.android.ui.products.selector.ProductSelectorViewModel
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit
Expand All @@ -34,14 +36,18 @@ import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.wordpress.android.fluxc.network.rest.wpcom.wc.order.CoreOrderStatus
import org.wordpress.android.fluxc.store.WCProductStore
import java.math.BigDecimal
import java.util.function.Consumer

@ExperimentalCoroutinesApi
class CreationFocusedOrderCreateEditViewModelTest : UnifiedOrderEditViewModelTest() {
override val mode: Mode = Creation
override val sku: String = "123"
override val tracksFlow: String = VALUE_FLOW_CREATION

companion object {
Expand Down Expand Up @@ -1109,4 +1115,56 @@ class CreationFocusedOrderCreateEditViewModelTest : UnifiedOrderEditViewModelTes
mapOf(AnalyticsTracker.KEY_FLOW to VALUE_FLOW_CREATION)
)
}

@Test
fun `given sku, when view model init, then fetch product information`() {
testBlocking {
val navArgs = OrderCreateEditFormFragmentArgs(
OrderCreateEditViewModel.Mode.Creation, "123"
).initSavedStateHandle()
whenever(parameterRepository.getParameters("parameters_key", navArgs)).thenReturn(
SiteParameters(
currencyCode = "",
currencySymbol = null,
currencyFormattingParameters = null,
weightUnit = null,
dimensionUnit = null,
gmtOffset = 0F
)
)

createSut(navArgs)

verify(productListRepository, times(2)).searchProductList(
"123",
WCProductStore.SkuSearchOptions.ExactSearch
)
}
}

@Test
fun `given empty sku, when view model init, then do not fetch product information`() {
testBlocking {
val navArgs = OrderCreateEditFormFragmentArgs(
OrderCreateEditViewModel.Mode.Creation, ""
).initSavedStateHandle()
whenever(parameterRepository.getParameters("parameters_key", navArgs)).thenReturn(
SiteParameters(
currencyCode = "",
currencySymbol = null,
currencyFormattingParameters = null,
weightUnit = null,
dimensionUnit = null,
gmtOffset = 0F
)
)

createSut(navArgs)

verify(productListRepository, times(1)).searchProductList(
"123",
WCProductStore.SkuSearchOptions.ExactSearch
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.mockito.kotlin.verify
@RunWith(MockitoJUnitRunner.Silent::class)
class EditFocusedOrderCreateEditViewModelTest : UnifiedOrderEditViewModelTest() {
override val mode: Mode = Edit(defaultOrderValue.id)
override val sku: String = "123"
override val tracksFlow: String = VALUE_FLOW_EDITING

override fun initMocksForAnalyticsWithOrder(order: Order) {
Expand Down
Loading