From c8cd43663bd4276e61b2a75aa5ca60809f842928 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 17 Sep 2025 18:07:43 +0100 Subject: [PATCH 1/3] Hide split shipments for CIAB sites --- .../WooShippingLabelCreationViewModel.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt index 31e427a71563..63caae4b4e7d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt @@ -16,6 +16,8 @@ import com.woocommerce.android.analytics.AnalyticsTracker.Companion.KEY_ERROR import com.woocommerce.android.analytics.AnalyticsTracker.Companion.KEY_STATE import com.woocommerce.android.analytics.AnalyticsTracker.Companion.VALUE_STARTED import com.woocommerce.android.analytics.AnalyticsTrackerWrapper +import com.woocommerce.android.ciab.CIABAffectedFeature +import com.woocommerce.android.ciab.CIABSiteGateKeeper import com.woocommerce.android.extensions.combine import com.woocommerce.android.extensions.sumByFloat import com.woocommerce.android.model.Address @@ -124,6 +126,7 @@ class WooShippingLabelCreationViewModel @Inject constructor( private val fetchShippingLabelFile: FetchShippingLabelFile, private val observeShippingLabelStatus: ObserveShippingLabelStatus, private val downloadAndPrintInvoiceUseCase: DownloadAndPrintInvoiceUseCase, + private val ciabSiteGateKeeper: CIABSiteGateKeeper, private val analyticsTracker: AnalyticsTrackerWrapper, ) : ScopedViewModel(savedState) { private val navArgs: WooShippingLabelCreationFragmentArgs by savedState.navArgs() @@ -779,6 +782,9 @@ class WooShippingLabelCreationViewModel @Inject constructor( formattedPrice = shipmentUIList[uiState.selectedIndex].shipmentCostUI?.formattedTotalPrice, onMarkOrderCompleteChange = ::onMarkOrderCompleteChange, onPurchaseShippingLabel = ::onPurchaseShippingLabel + ), + isSplitShipmentsSupported = ciabSiteGateKeeper.isFeatureSupported( + feature = CIABAffectedFeature.WooShippingSplitShipments ) ) }.combine(loadTrigger.onStart { emit(Unit) }) { viewState, _ -> @@ -1283,12 +1289,14 @@ class WooShippingLabelCreationViewModel @Inject constructor( val uiState: UIControlsState, val destinationStatus: AddressStatus, val paymentsSectionUI: PaymentsSectionUI, - val purchaseSectionUI: PurchaseSectionUI + val purchaseSectionUI: PurchaseSectionUI, + val isSplitShipmentsSupported: Boolean ) : WooShippingViewState() { val shouldShowSplitShipmentButton: Boolean get() { val unpurchasedShipments = shipmentUIList.filterNot { it.isPurchased } - return shipmentUIList.none { it.isPurchaseInProgress } && + return isSplitShipmentsSupported && + shipmentUIList.none { it.isPurchaseInProgress } && ( unpurchasedShipments.size > 1 || (unpurchasedShipments.firstOrNull()?.totalItemQuantity ?: 0) > 1 From a33539c80a0964c4415352349feaf4312d147ad4 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 17 Sep 2025 18:14:16 +0100 Subject: [PATCH 2/3] Add unit tests --- .../WooShippingLabelCreationViewModelTest.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModelTest.kt index e4242dc0748e..c619ea27ece5 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModelTest.kt @@ -9,6 +9,8 @@ import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.analytics.AnalyticsTracker.Companion.KEY_ERROR import com.woocommerce.android.analytics.AnalyticsTracker.Companion.KEY_STATE import com.woocommerce.android.analytics.AnalyticsTrackerWrapper +import com.woocommerce.android.ciab.CIABAffectedFeature +import com.woocommerce.android.ciab.CIABSiteGateKeeper import com.woocommerce.android.model.Address import com.woocommerce.android.model.AmbiguousLocation import com.woocommerce.android.model.Location @@ -330,6 +332,9 @@ class WooShippingLabelCreationViewModelTest : BaseUnitTest() { private val file: File = mock() private val analyticsTracker: AnalyticsTrackerWrapper = mock() private val createDefaultCustomsData = CreateDefaultCustomsData(mock()) + private val ciabSiteGateKeeper: CIABSiteGateKeeper = mock { + on { isFeatureSupported(CIABAffectedFeature.WooShippingSplitShipments) } doReturn true + } private lateinit var sut: WooShippingLabelCreationViewModel @@ -355,6 +360,7 @@ class WooShippingLabelCreationViewModelTest : BaseUnitTest() { observeShippingLabelStatus = observeShippingLabelStatus, downloadAndPrintInvoiceUseCase = mock(), analyticsTracker = analyticsTracker, + ciabSiteGateKeeper = ciabSiteGateKeeper, savedState = savedState ) } @@ -1809,4 +1815,30 @@ class WooShippingLabelCreationViewModelTest : BaseUnitTest() { @Suppress("UnusedFlow") verify(observeShippingLabelStatus).invoke(orderId, inProgressLabel.labelId) } + + @Test + fun `given split shipments unsupported, when displaying shipments, then hide split option`() = testBlocking { + // The default `getShipments` mock already returns a shipment with multiple items + given(ciabSiteGateKeeper.isFeatureSupported(CIABAffectedFeature.WooShippingSplitShipments)) + .willReturn(false) + + createViewModel() + + val currentViewState = sut.viewState.value as DataState + + assertThat(currentViewState.shouldShowSplitShipmentButton).isFalse + } + + @Test + fun `given split shipments supported, when displaying shipments, then hide split option`() = testBlocking { + // The default `getShipments` mock already returns a shipment with multiple items + given(ciabSiteGateKeeper.isFeatureSupported(CIABAffectedFeature.WooShippingSplitShipments)) + .willReturn(true) + + createViewModel() + + val currentViewState = sut.viewState.value as DataState + + assertThat(currentViewState.shouldShowSplitShipmentButton).isTrue + } } From 454a031147d5ee8873eeb9f4bdd6cbf0d17eba81 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 17 Sep 2025 18:44:33 +0100 Subject: [PATCH 3/3] Extract logic to variable to improve readability --- .../wooshippinglabels/WooShippingLabelCreationViewModel.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt index 63caae4b4e7d..cd2acc4468fb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationViewModel.kt @@ -1295,12 +1295,11 @@ class WooShippingLabelCreationViewModel @Inject constructor( val shouldShowSplitShipmentButton: Boolean get() { val unpurchasedShipments = shipmentUIList.filterNot { it.isPurchased } + val hasMultipleUnfulfilledItems = unpurchasedShipments.size > 1 || + (unpurchasedShipments.firstOrNull()?.totalItemQuantity ?: 0) > 1 return isSplitShipmentsSupported && shipmentUIList.none { it.isPurchaseInProgress } && - ( - unpurchasedShipments.size > 1 || - (unpurchasedShipments.firstOrNull()?.totalItemQuantity ?: 0) > 1 - ) + hasMultipleUnfulfilledItems } } }