Skip to content

Commit

Permalink
Merge branch 'trunk' into issue-4614/improve-shipping-labels-validati…
Browse files Browse the repository at this point in the history
…on-scrolling
  • Loading branch information
Joel Dean committed Feb 2, 2024
2 parents a9b2643 + 57f48eb commit 4af451b
Show file tree
Hide file tree
Showing 30 changed files with 1,314 additions and 300 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
17.3
-----
- [*] [Internal] Enhanced user experience in shipping label creation with automatic scrolling to the first invalid field upon form submission failure [https://github.com/woocommerce/woocommerce-android/pull/10657]
17.2
-----
- [**] [Available for users with WooCommerce version of 8.7+, which is not released yet] Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650]

17.1
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ enum class AnalyticsEvent(val siteless: Boolean = false) {
RECEIPT_PRINT_CANCELED,
RECEIPT_PRINT_SUCCESS,
RECEIPT_VIEW_TAPPED,
RECEIPT_URL_FETCHING_FAILS,

// -- Top-level navigation
MAIN_MENU_SETTINGS_TAPPED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class OrderDetailFragment :
private fun setupObservers(viewModel: OrderDetailViewModel) {
viewModel.viewStateData.observe(viewLifecycleOwner) { old, new ->
new.orderInfo?.takeIfNotEqualTo(old?.orderInfo) {
showOrderDetail(it.order!!, it.isPaymentCollectableWithCardReader, it.isReceiptButtonsVisible)
showOrderDetail(it.order!!, it.isPaymentCollectableWithCardReader, it.receiptButtonStatus)
requireActivity().invalidateOptionsMenu()
}
new.orderStatus?.takeIfNotEqualTo(old?.orderStatus) { showOrderStatus(it) }
Expand Down Expand Up @@ -437,7 +437,7 @@ class OrderDetailFragment :
private fun showOrderDetail(
order: Order,
isPaymentCollectableWithCardReader: Boolean,
isReceiptButtonsVisible: Boolean
receiptButtonStatus: OrderDetailViewState.ReceiptButtonStatus
) {
binding.orderDetailOrderStatus.updateOrder(order)
binding.orderDetailShippingMethodNotice.isVisible = order.hasMultipleShippingLines
Expand All @@ -449,7 +449,7 @@ class OrderDetailFragment :
binding.orderDetailPaymentInfo.updatePaymentInfo(
order = order,
isPaymentCollectableWithCardReader = isPaymentCollectableWithCardReader,
isReceiptAvailable = isReceiptButtonsVisible,
receiptButtonStatus = receiptButtonStatus,
formatCurrencyForDisplay = currencyFormatter.buildBigDecimalFormatter(order.currency),
onIssueRefundClickListener = { viewModel.onIssueOrderRefundClicked() },
onSeeReceiptClickListener = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import com.woocommerce.android.analytics.AnalyticsEvent
import com.woocommerce.android.analytics.AnalyticsTracker
import com.woocommerce.android.analytics.AnalyticsTrackerWrapper
import com.woocommerce.android.model.Order
import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker
import org.wordpress.android.fluxc.store.WCOrderStore
import javax.inject.Inject

class OrderDetailTracker @Inject constructor(
private val trackerWrapper: AnalyticsTrackerWrapper
private val trackerWrapper: AnalyticsTrackerWrapper,
private val paymentsFlowTracker: PaymentsFlowTracker,
) {
fun trackCustomFieldsTapped() {
trackerWrapper.track(AnalyticsEvent.ORDER_VIEW_CUSTOM_FIELDS_TAPPED)
Expand All @@ -24,9 +26,8 @@ class OrderDetailTracker @Inject constructor(
)
}

fun trackReceiptViewTapped(orderId: Long, orderStatus: Order.Status) {
trackerWrapper.track(
AnalyticsEvent.RECEIPT_VIEW_TAPPED,
suspend fun trackReceiptViewTapped(orderId: Long, orderStatus: Order.Status) {
paymentsFlowTracker.trackReceiptViewTapped(
mapOf(
AnalyticsTracker.KEY_ORDER_ID to orderId,
AnalyticsTracker.KEY_STATUS to orderStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import com.woocommerce.android.ui.orders.OrderStatusUpdateSource
import com.woocommerce.android.ui.orders.details.customfields.CustomOrderFieldsHelper
import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam
import com.woocommerce.android.ui.payments.cardreader.payment.CardReaderPaymentCollectibilityChecker
import com.woocommerce.android.ui.payments.receipt.PaymentReceiptHelper
import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker
import com.woocommerce.android.ui.products.ProductDetailRepository
import com.woocommerce.android.ui.products.addons.AddonRepository
Expand Down Expand Up @@ -91,7 +92,8 @@ class OrderDetailViewModel @Inject constructor(
private val getOrderSubscriptions: GetOrderSubscriptions,
private val giftCardRepository: GiftCardRepository,
private val orderProductMapper: OrderProductMapper,
private val productDetailRepository: ProductDetailRepository
private val productDetailRepository: ProductDetailRepository,
private val paymentReceiptHelper: PaymentReceiptHelper,
) : ScopedViewModel(savedState), OnProductFetchedListener {
private val navArgs: OrderDetailFragmentArgs by savedState.navArgs()

Expand All @@ -101,9 +103,13 @@ class OrderDetailViewModel @Inject constructor(
get() = requireNotNull(viewState.orderInfo?.order)
set(value) {
viewState = viewState.copy(
orderInfo = OrderDetailViewState.OrderInfo(
orderInfo = viewState.orderInfo?.copy(
order = value,
isPaymentCollectableWithCardReader = viewState.orderInfo?.isPaymentCollectableWithCardReader
?: false
) ?: OrderDetailViewState.OrderInfo(
value,
viewState.orderInfo?.isPaymentCollectableWithCardReader ?: false
isPaymentCollectableWithCardReader = false
)
)
}
Expand Down Expand Up @@ -343,10 +349,32 @@ class OrderDetailViewModel @Inject constructor(
}

fun onSeeReceiptClicked() {
tracker.trackReceiptViewTapped(order.id, order.status)
loadReceiptUrl()?.let {
triggerEvent(PreviewReceipt(order.billingAddress.email, it, order.id))
} ?: WooLog.e(T.ORDERS, "ReceiptUrl is null, but SeeReceipt button is visible")
launch {
tracker.trackReceiptViewTapped(order.id, order.status)

viewState = viewState.copy(
orderInfo = viewState.orderInfo?.copy(
receiptButtonStatus = OrderDetailViewState.ReceiptButtonStatus.Loading
)
)

val receiptResult = paymentReceiptHelper.getReceiptUrl(order.id)

viewState = viewState.copy(
orderInfo = viewState.orderInfo?.copy(
receiptButtonStatus = OrderDetailViewState.ReceiptButtonStatus.Visible
)
)

if (receiptResult.isSuccess) {
triggerEvent(PreviewReceipt(order.billingAddress.email, receiptResult.getOrThrow(), order.id))
} else {
paymentsFlowTracker.trackReceiptUrlFetchingFails(
errorDescription = receiptResult.exceptionOrNull()?.message ?: "Unknown error",
)
triggerEvent(ShowSnackbar(string.receipt_fetching_error))
}
}
}

fun onPrintingInstructionsClicked() {
Expand All @@ -372,12 +400,6 @@ class OrderDetailViewModel @Inject constructor(
triggerEvent(ShowSnackbar(message))
}

private fun loadReceiptUrl(): String? {
return selectedSite.getIfExists()?.let {
appPrefs.getReceiptUrl(it.id, it.siteId, it.selfHostedSiteId, order.id)
}
}

fun onViewRefundedProductsClicked() {
triggerEvent(ViewRefundedProducts(orderId = order.id))
}
Expand Down Expand Up @@ -580,7 +602,11 @@ class OrderDetailViewModel @Inject constructor(
orderInfo = OrderDetailViewState.OrderInfo(
order = order,
isPaymentCollectableWithCardReader = isPaymentCollectable,
isReceiptButtonsVisible = !loadReceiptUrl().isNullOrEmpty()
receiptButtonStatus = if (paymentReceiptHelper.isReceiptAvailable(order.id) && order.isOrderPaid) {
OrderDetailViewState.ReceiptButtonStatus.Visible
} else {
OrderDetailViewState.ReceiptButtonStatus.Hidden
}
),
orderStatus = orderStatus,
toolbarTitle = resourceProvider.getString(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ data class OrderDetailViewState(
data class OrderInfo(
val order: Order? = null,
val isPaymentCollectableWithCardReader: Boolean = false,
val isReceiptButtonsVisible: Boolean = false
val receiptButtonStatus: ReceiptButtonStatus = ReceiptButtonStatus.Hidden,
) : Parcelable

enum class ReceiptButtonStatus {
Loading, Hidden, Visible
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.woocommerce.android.extensions.show
import com.woocommerce.android.model.GiftCardSummary
import com.woocommerce.android.model.Order
import com.woocommerce.android.model.Refund
import com.woocommerce.android.ui.orders.details.OrderDetailViewState
import com.woocommerce.android.ui.orders.details.adapter.OrderDetailRefundsAdapter
import com.woocommerce.android.ui.orders.details.adapter.OrderDetailRefundsLineBuilder
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -36,7 +37,7 @@ class OrderDetailPaymentInfoView @JvmOverloads constructor(
@Suppress("LongParameterList")
fun updatePaymentInfo(
order: Order,
isReceiptAvailable: Boolean,
receiptButtonStatus: OrderDetailViewState.ReceiptButtonStatus,
isPaymentCollectableWithCardReader: Boolean,
formatCurrencyForDisplay: (BigDecimal) -> String,
onSeeReceiptClickListener: (view: View) -> Unit,
Expand Down Expand Up @@ -88,7 +89,7 @@ class OrderDetailPaymentInfoView @JvmOverloads constructor(
updateFeesSection(order, formatCurrencyForDisplay)
updateRefundSection(order, formatCurrencyForDisplay, onIssueRefundClickListener)
updateCollectPaymentSection(order, onCollectPaymentClickListener)
updateSeeReceiptSection(isReceiptAvailable, onSeeReceiptClickListener)
updateSeeReceiptSection(receiptButtonStatus, onSeeReceiptClickListener)
updatePrintingInstructionSection(isPaymentCollectableWithCardReader, onPrintingInstructionsClickListener)
}

Expand Down Expand Up @@ -192,16 +193,26 @@ class OrderDetailPaymentInfoView @JvmOverloads constructor(
}

private fun updateSeeReceiptSection(
isReceiptAvailable: Boolean,
receiptButtonStatus: OrderDetailViewState.ReceiptButtonStatus,
onSeeReceiptClickListener: (view: View) -> Unit
) {
if (isReceiptAvailable) {
binding.paymentInfoSeeReceiptButton.visibility = VISIBLE
binding.paymentInfoSeeReceiptButton.setOnClickListener(
onSeeReceiptClickListener
)
} else {
binding.paymentInfoSeeReceiptButton.visibility = GONE
when (receiptButtonStatus) {
OrderDetailViewState.ReceiptButtonStatus.Loading -> {
binding.paymentInfoSeeReceiptButton.visibility = VISIBLE
binding.paymentInfoSeeReceiptButton.isEnabled = false
binding.paymentInfoSeeReceiptButtonProgressBar.visibility = VISIBLE
}
OrderDetailViewState.ReceiptButtonStatus.Hidden -> {
binding.paymentInfoSeeReceiptButton.visibility = GONE
binding.paymentInfoSeeReceiptButtonProgressBar.visibility = GONE
}
OrderDetailViewState.ReceiptButtonStatus.Visible -> {
binding.paymentInfoSeeReceiptButtonProgressBar.visibility = GONE
binding.paymentInfoSeeReceiptButton.visibility = VISIBLE
binding.paymentInfoSeeReceiptButton.setOnClickListener(
onSeeReceiptClickListener
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ import org.wordpress.android.fluxc.store.WCInPersonPaymentsStore.InPersonPayment
import org.wordpress.android.fluxc.store.WooCommerceStore
import javax.inject.Inject

const val WCPAY_RECEIPTS_SENDING_SUPPORT_VERSION = "4.0.0"

/**
* This class is used to check if the selected store is ready to accept In Person Payments. The app should check store's
* eligibility every time it attempts to connect to a card reader.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import com.woocommerce.android.R
import com.woocommerce.android.analytics.AnalyticsTracker
import com.woocommerce.android.databinding.CardReaderPaymentDialogBinding
import com.woocommerce.android.extensions.navigateBackWithNotice
import com.woocommerce.android.model.UiString
import com.woocommerce.android.support.help.HelpOrigin
import com.woocommerce.android.support.requests.SupportRequestFormActivity
import com.woocommerce.android.ui.base.UIMessageResolver
Expand All @@ -32,7 +31,6 @@ import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.BuiltInR
import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.ExternalReaderPaymentSuccessfulReceiptSentAutomaticallyState
import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.ExternalReaderPaymentSuccessfulState
import com.woocommerce.android.ui.payments.refunds.RefundSummaryFragment.Companion.KEY_INTERAC_SUCCESS
import com.woocommerce.android.util.ActivityUtils
import com.woocommerce.android.util.PrintHtmlHelper
import com.woocommerce.android.util.UiHelpers
import com.woocommerce.android.util.UiHelpers.getTextOfUiString
Expand Down Expand Up @@ -86,7 +84,6 @@ class CardReaderPaymentDialogFragment : PaymentsBaseDialogFragment(R.layout.card
event.documentName
)
InteracRefundSuccessful -> navigateBackWithNotice(KEY_INTERAC_SUCCESS)
is SendReceipt -> composeEmail(event.address, event.subject, event.content)
is ShowSnackbar -> uiMessageResolver.showSnack(event.message)
is ShowSnackbarInDialog -> Snackbar.make(
requireView(), event.message, BaseTransientBottomBar.LENGTH_LONG
Expand Down Expand Up @@ -186,12 +183,6 @@ class CardReaderPaymentDialogFragment : PaymentsBaseDialogFragment(R.layout.card
mp.start()
}

private fun composeEmail(address: String, subject: UiString, content: UiString) {
ActivityUtils.sendEmail(requireActivity(), address, subject, content) {
viewModel.onEmailActivityNotFound()
}
}

override fun onResume() {
super.onResume()
AnalyticsTracker.trackViewShown(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ class CardReaderPaymentOrderHelper @Inject constructor(
fun getAmountLabel(order: Order): String = currencyFormatter
.formatAmountWithCurrency(order.total.toDouble(), order.currency)

fun getReceiptDocumentName(order: Order) = "receipt-order-${order.id}"
fun getReceiptDocumentName(orderId: Long) = "receipt-order-$orderId"
}
Loading

0 comments on commit 4af451b

Please sign in to comment.