Skip to content

Commit

Permalink
Merge pull request #13022 from woocommerce/issue/13017-product-global…
Browse files Browse the repository at this point in the history
…-unique-id-edit-value

[Product Global Unique Id] Edit and Validate Value
  • Loading branch information
toupper authored Nov 28, 2024
2 parents 5d96bce + a934e1a commit f65200b
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ import org.wordpress.android.fluxc.store.WCProductStore
* Returns whether the error message is meaningful and can be displayed to the user.
*/
val WCProductStore.ProductError.canDisplayMessage: Boolean
get() = this.type == WCProductStore.ProductErrorType.INVALID_MIN_MAX_QUANTITY &&
get() = (
this.type == WCProductStore.ProductErrorType.INVALID_MIN_MAX_QUANTITY ||
this.type == WCProductStore.ProductErrorType.GENERIC_ERROR
) &&
this.message.isNotEmpty()
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class ProductInventoryFragment :
new.skuErrorMessage?.takeIfNotEqualTo(old?.skuErrorMessage) {
displaySkuError(it)
}
new.globalUniqueIdErrorMessage?.takeIfNotEqualTo(old?.globalUniqueIdErrorMessage) {
displayGlobalUniqueIdErrorMessage(it)
}
new.isStockManagementVisible?.takeIfNotEqualTo(old?.isStockManagementVisible) { isVisible ->
binding.stockManagementPanel.isVisible = isVisible
binding.soldIndividuallySwitch.isVisible = isVisible && new.isIndividualSaleSwitchVisible == true
Expand Down Expand Up @@ -148,6 +151,14 @@ class ProductInventoryFragment :
}
}

private fun displayGlobalUniqueIdErrorMessage(messageId: Int) {
if (messageId != 0) {
binding.productGlobalUniqueId.error = getString(messageId)
} else {
binding.productGlobalUniqueId.helperText = getString(R.string.product_global_unique_id_summary)
}
}

private fun setupViews() {
if (!isAdded) return

Expand Down Expand Up @@ -220,6 +231,10 @@ class ProductInventoryFragment :

with(binding.productGlobalUniqueId) {
visibility = if (featureIsEnabled) View.VISIBLE else View.GONE

setOnTextChangedListener {
viewModel.onProductUniqueGlobalIdChanged(it.toString())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,19 @@ class ProductInventoryViewModel @Inject constructor(
}
}

fun onProductUniqueGlobalIdChanged(globalUniqueId: String) {
onDataChanged(globalUniqueId = globalUniqueId)

if (isOnlyNumbersAndHyphens(globalUniqueId)) {
clearGlobalUniqueIdError()
} else {
showGlobalUniqueIdError()
}
}

fun onDataChanged(
sku: String? = inventoryData.sku,
globalUniqueId: String? = inventoryData.globalUniqueId,
backorderStatus: ProductBackorderStatus? = inventoryData.backorderStatus,
isSoldIndividually: Boolean? = inventoryData.isSoldIndividually,
isStockManaged: Boolean? = inventoryData.isStockManaged,
Expand All @@ -115,6 +126,7 @@ class ProductInventoryViewModel @Inject constructor(
viewState = viewState.copy(
inventoryData = InventoryData(
sku = sku,
globalUniqueId = globalUniqueId,
backorderStatus = backorderStatus,
isSoldIndividually = isSoldIndividually,
isStockManaged = isStockManaged,
Expand All @@ -129,7 +141,7 @@ class ProductInventoryViewModel @Inject constructor(
AnalyticsEvent.PRODUCT_INVENTORY_SETTINGS_DONE_BUTTON_TAPPED,
mapOf(AnalyticsTracker.KEY_HAS_CHANGED_DATA to hasChanges)
)
if (hasChanges && !hasSkuError()) {
if (hasChanges && !hasSkuError() && !hasGlobalUniqueIdError()) {
triggerEvent(ExitWithResult(inventoryData))
} else {
triggerEvent(Exit)
Expand All @@ -144,8 +156,26 @@ class ProductInventoryViewModel @Inject constructor(
viewState = viewState.copy(skuErrorMessage = string.product_inventory_update_sku_error)
}

private fun clearGlobalUniqueIdError() {
viewState = viewState.copy(globalUniqueIdErrorMessage = 0)
}

private fun showGlobalUniqueIdError() {
viewState = viewState.copy(globalUniqueIdErrorMessage = string.product_inventory_update_global_unique_id_error)
}

private fun hasSkuError() = viewState.skuErrorMessage != 0 && viewState.skuErrorMessage != null

private fun hasGlobalUniqueIdError() = viewState.globalUniqueIdErrorMessage != 0 &&
viewState.globalUniqueIdErrorMessage != null

private fun isOnlyNumbersAndHyphens(input: String): Boolean {
// Define the regex pattern to match only numbers and hyphens
val pattern = "^[0-9-]+$"
// Check if the input string matches the pattern
return input.matches(pattern.toRegex())
}

override fun onCleared() {
super.onCleared()
productRepository.onCleanup()
Expand All @@ -155,6 +185,7 @@ class ProductInventoryViewModel @Inject constructor(
data class ViewState(
val inventoryData: InventoryData = InventoryData(),
val skuErrorMessage: Int? = null,
val globalUniqueIdErrorMessage: Int? = null,
val isIndividualSaleSwitchVisible: Boolean? = null,
val isStockStatusVisible: Boolean? = null,
val isStockManagementVisible: Boolean? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ class ProductDetailFragment :
handleResult<InventoryData>(BaseProductEditorFragment.KEY_INVENTORY_DIALOG_RESULT) {
viewModel.updateProductDraft(
sku = it.sku,
globalUniqueId = it.globalUniqueId,
soldIndividually = it.isSoldIndividually,
stockStatus = it.stockStatus,
stockQuantity = it.stockQuantity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,7 @@ class ProductDetailViewModel @Inject constructor(
shortDescription: String? = null,
title: String? = null,
sku: String? = null,
globalUniqueId: String? = null,
slug: String? = null,
manageStock: Boolean? = null,
stockStatus: ProductStockStatus? = null,
Expand Down Expand Up @@ -1299,6 +1300,7 @@ class ProductDetailViewModel @Inject constructor(
shortDescription = shortDescription ?: product.shortDescription,
name = title ?: product.name,
sku = sku ?: product.sku,
globalUniqueId = globalUniqueId ?: product.globalUniqueId,
slug = slug ?: product.slug,
isStockManaged = manageStock ?: product.isStockManaged,
stockStatus = stockStatus ?: product.stockStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class VariationDetailFragment :
handleResult<InventoryData>(BaseProductEditorFragment.KEY_INVENTORY_DIALOG_RESULT) {
viewModel.onVariationChanged(
sku = it.sku,
globalUniqueId = it.globalUniqueId,
stockStatus = it.stockStatus,
stockQuantity = it.stockQuantity,
backorderStatus = it.backorderStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class VariationDetailViewModel @Inject constructor(
remoteProductId: Long? = null,
remoteVariationId: Long? = null,
sku: String? = null,
globalUniqueId: String? = null,
image: Optional<Image>? = null,
regularPrice: BigDecimal? = viewState.variation?.regularPrice,
salePrice: BigDecimal? = viewState.variation?.salePrice,
Expand Down Expand Up @@ -243,6 +244,7 @@ class VariationDetailViewModel @Inject constructor(
remoteProductId = remoteProductId ?: variation.remoteProductId,
remoteVariationId = remoteVariationId ?: variation.remoteVariationId,
sku = sku ?: variation.sku,
globalUniqueId = globalUniqueId ?: variation.globalUniqueId,
image = if (image != null) image.value else variation.image,
regularPrice = regularPrice,
salePrice = salePrice,
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 @@ -2114,6 +2114,7 @@
<string name="product_inventory_quantity">Quantity</string>
<string name="product_inventory_quantity_summary">How many items are in stock</string>
<string name="product_inventory_update_sku_error">SKU already in use by another product</string>
<string name="product_inventory_update_global_unique_id_error">Please enter only numbers and hyphens</string>
<string name="product_inventory_update_stock_quantity_error">Please enter a number</string>
<string name="product_pricing_update_sale_price_error">Sale price must be less than regular price</string>
<string name="product_pricing_scheduled_sale_price_error">You must set the sale price if a sale is scheduled</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ProductInventoryViewModelTest : BaseUnitTest() {

private val initialData = InventoryData(
"SKU123",
globalUniqueId = "123-456",
isStockManaged = false,
isSoldIndividually = false,
stockStatus = InStock,
Expand All @@ -44,6 +45,7 @@ class ProductInventoryViewModelTest : BaseUnitTest() {

private val initialDataWithNonWholeDecimalQuantity = InventoryData(
"SKU123",
globalUniqueId = "123-456",
isStockManaged = true,
isSoldIndividually = false,
stockStatus = InStock,
Expand All @@ -53,6 +55,7 @@ class ProductInventoryViewModelTest : BaseUnitTest() {

private val expectedData = InventoryData(
"SKU321",
globalUniqueId = "123-456",
isStockManaged = true,
isSoldIndividually = true,
stockStatus = OutOfStock,
Expand Down Expand Up @@ -98,6 +101,7 @@ class ProductInventoryViewModelTest : BaseUnitTest() {

viewModel.onDataChanged(
expectedData.sku,
expectedData.globalUniqueId,
expectedData.backorderStatus,
expectedData.isSoldIndividually,
expectedData.isStockManaged,
Expand Down Expand Up @@ -131,6 +135,27 @@ class ProductInventoryViewModelTest : BaseUnitTest() {
}

@Test
fun `Test that an error is shown if the global unique id contains characters other than numbers and hyphens`() =
testBlocking {
val invalidGlobalUniqueId = "invalid"
val validGlobalUniqueId = "123-456"
var actual: ViewState? = null
viewModel.viewStateData.observeForever { _, new ->
actual = new
}

viewModel.onProductUniqueGlobalIdChanged(invalidGlobalUniqueId)

assertThat(actual?.inventoryData?.globalUniqueId).isEqualTo(invalidGlobalUniqueId)
assertThat(actual?.globalUniqueIdErrorMessage)
.isEqualTo(string.product_inventory_update_global_unique_id_error)

viewModel.onProductUniqueGlobalIdChanged(validGlobalUniqueId)

assertThat(actual?.inventoryData?.globalUniqueId).isEqualTo(validGlobalUniqueId)
assertThat(actual?.globalUniqueIdErrorMessage).isEqualTo(0)
}

fun `Test that a discard dialog isn't shown if no data changed`() =
testBlocking {
val events = mutableListOf<Event>()
Expand All @@ -156,6 +181,7 @@ class ProductInventoryViewModelTest : BaseUnitTest() {

viewModel.onDataChanged(
expectedData.sku,
expectedData.globalUniqueId,
expectedData.backorderStatus,
expectedData.isSoldIndividually,
expectedData.isStockManaged,
Expand Down

0 comments on commit f65200b

Please sign in to comment.