Skip to content

Commit 71554f1

Browse files
committed
Merge branch 'feat/WOOMOB-1155-pos-orders-analytics' of https://github.com/woocommerce/woocommerce-android into feat/WOOMOB-1155-pos-orders-analytics
2 parents d3abf2e + 5e1dd87 commit 71554f1

File tree

20 files changed

+1330
-1719
lines changed

20 files changed

+1330
-1719
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/DropDown.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import androidx.compose.foundation.layout.Box
44
import androidx.compose.foundation.layout.safeContentPadding
55
import androidx.compose.material3.DropdownMenuItem
66
import androidx.compose.material3.ExperimentalMaterial3Api
7+
import androidx.compose.material3.ExposedDropdownMenuAnchorType
78
import androidx.compose.material3.ExposedDropdownMenuBox
89
import androidx.compose.material3.ExposedDropdownMenuDefaults
910
import androidx.compose.material3.MaterialTheme
10-
import androidx.compose.material3.MenuAnchorType
1111
import androidx.compose.material3.OutlinedTextField
1212
import androidx.compose.material3.Text
1313
import androidx.compose.runtime.Composable
@@ -52,7 +52,7 @@ fun <T> WCExposedDropDown(
5252
readOnly = true,
5353
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
5454
modifier = Modifier
55-
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
55+
.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
5656
.focusRequester(focusRequester)
5757
)
5858

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/components/ShipmentsTabRow.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import androidx.compose.foundation.layout.Row
55
import androidx.compose.foundation.layout.size
66
import androidx.compose.material3.Icon
77
import androidx.compose.material3.MaterialTheme
8-
import androidx.compose.material3.ScrollableTabRow
8+
import androidx.compose.material3.PrimaryScrollableTabRow
99
import androidx.compose.material3.Tab
1010
import androidx.compose.material3.Text
1111
import androidx.compose.runtime.Composable
@@ -34,7 +34,7 @@ fun ShipmentsTabRow(
3434
modifier: Modifier = Modifier
3535
) {
3636
val scope = rememberCoroutineScope()
37-
ScrollableTabRow(
37+
PrimaryScrollableTabRow(
3838
selectedTabIndex = selectedTabIndex,
3939
containerColor = MaterialTheme.colorScheme.surface,
4040
contentColor = MaterialTheme.colorScheme.primary,

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/PackageItemComponents.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,7 @@ fun WooShippingPackageListItem(
5555
onPackageStarred = onPackageStarred
5656
)
5757
} else {
58-
val swipeToDismissBoxState = rememberSwipeToDismissBoxState(
59-
confirmValueChange = {
60-
if (it == SwipeToDismissBoxValue.EndToStart) onPackageRemoved(packageData)
61-
it != SwipeToDismissBoxValue.EndToStart
62-
}
63-
)
58+
val swipeToDismissBoxState = rememberSwipeToDismissBoxState()
6459

6560
SwipeToDismissBox(
6661
state = swipeToDismissBoxState,
@@ -79,6 +74,10 @@ fun WooShippingPackageListItem(
7974
tint = colorResource(R.color.woo_white)
8075
)
8176
}
77+
},
78+
onDismiss = {
79+
if (it == SwipeToDismissBoxValue.EndToStart) onPackageRemoved(packageData)
80+
it != SwipeToDismissBoxValue.EndToStart
8281
}
8382
) {
8483
WooShippingPackageListItemContent(

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosCard.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import androidx.compose.ui.graphics.toArgb
2525
import androidx.compose.ui.input.pointer.pointerInput
2626
import androidx.compose.ui.platform.LocalDensity
2727
import androidx.compose.ui.semantics.isTraversalGroup
28+
import androidx.compose.ui.semantics.selected
2829
import androidx.compose.ui.semantics.semantics
2930
import androidx.compose.ui.text.style.TextAlign
3031
import androidx.compose.ui.unit.Density
@@ -48,9 +49,9 @@ fun WooPosCard(
4849
shape: Shape = MaterialTheme.shapes.medium,
4950
backgroundColor: Color = MaterialTheme.colorScheme.surfaceContainerLowest,
5051
contentColor: Color = contentColorFor(backgroundColor),
51-
border: BorderStroke? = null,
5252
elevation: WooPosElevation = WooPosElevation.Medium,
5353
shadowType: ShadowType = ShadowType.Normal,
54+
isSelected: Boolean = false,
5455
content: @Composable () -> Unit
5556
) {
5657
CompositionLocalProvider(
@@ -61,13 +62,21 @@ fun WooPosCard(
6162
.surface(
6263
shape = shape,
6364
backgroundColor = backgroundColor,
64-
border = border,
65+
border = if (isSelected) {
66+
BorderStroke(
67+
width = 2.dp,
68+
color = MaterialTheme.colorScheme.onSurface,
69+
)
70+
} else {
71+
null
72+
},
6573
elevation = elevation.value,
6674
shadowType = shadowType
6775
)
6876
.semantics(mergeDescendants = false) {
6977
isTraversalGroup = true
7078
}
79+
.semantics { selected = isSelected }
7180
.pointerInput(Unit) {},
7281
propagateMinConstraints = true
7382
) {

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/emailreceipt/WooPosEmailReceiptRepository.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class WooPosEmailReceiptRepository @Inject constructor(
2222
private val getWooCoreVersion: GetWooCorePluginCachedVersion
2323
) {
2424
suspend fun sendReceiptByEmail(orderId: Long, email: String): Result<Unit> = withContext(Dispatchers.IO) {
25-
val order = getOrderById(orderId)
25+
val order = getOrderById(orderId) ?: fetchOrderById(orderId)
2626
if (order == null) {
2727
return@withContext Result.failure(Exception("Failed to get order"))
2828
}
@@ -65,6 +65,19 @@ class WooPosEmailReceiptRepository @Inject constructor(
6565
orderMapper.toAppModel(it)
6666
}
6767

68+
private suspend fun fetchOrderById(orderId: Long): Order? {
69+
val result = orderStore.fetchSingleOrder(
70+
selectedSite.get(),
71+
orderId
72+
)
73+
74+
return if (!result.isError) {
75+
getOrderById(orderId)
76+
} else {
77+
null
78+
}
79+
}
80+
6881
private fun isWooCoreSupportsPOSReceipts(): Boolean {
6982
val wooCoreVersion = getWooCoreVersion() ?: return false
7083
return wooCoreVersion.semverCompareTo(WC_VERSION_SUPPORTS_POS_RECEIPTS) >= 0

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosLocalCatalogSyncRepository.kt

Lines changed: 27 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.woocommerce.android.ui.woopos.localcatalog
22

33
import com.woocommerce.android.ui.woopos.common.util.WooPosLogWrapper
4-
import com.woocommerce.android.ui.woopos.localcatalog.WooPosSyncProductsAction.WooPosSyncProductsResult
5-
import com.woocommerce.android.ui.woopos.localcatalog.WooPosSyncVariationsAction.WooPosSyncVariationsResult
64
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
75
import com.woocommerce.android.ui.woopos.util.datastore.WooPosSyncTimestampManager
86
import com.woocommerce.android.util.CoroutineDispatchers
@@ -35,6 +33,7 @@ class WooPosLocalCatalogSyncRepository @Inject constructor(
3533
private val dispatchers: CoroutineDispatchers,
3634
private val logger: WooPosLogWrapper,
3735
private val posLocalCatalogStore: WooPosLocalCatalogStore,
36+
private val dateTimeProvider: DateTimeProvider,
3837
) {
3938
companion object {
4039
const val PAGE_SIZE = 100
@@ -52,7 +51,7 @@ class WooPosLocalCatalogSyncRepository @Inject constructor(
5251
maxTotalItems = MAX_TOTAL_ITEMS_FULL_SYNC
5352
).also {
5453
if (it is PosLocalCatalogSyncResult.Success) {
55-
syncTimestampManager.storeFullSyncLastCompletedTimestamp(System.currentTimeMillis())
54+
syncTimestampManager.storeFullSyncLastCompletedTimestamp(dateTimeProvider.now())
5655
}
5756
if (it is PosLocalCatalogSyncResult.Failure.CatalogTooLarge) {
5857
preferencesRepository.disablePeriodicSyncForSite(site.siteId)
@@ -81,7 +80,7 @@ class WooPosLocalCatalogSyncRepository @Inject constructor(
8180
maxTotalItems: Int,
8281
modifiedAfterGmt: String? = null,
8382
): PosLocalCatalogSyncResult {
84-
val startTime = System.currentTimeMillis()
83+
val startTime = dateTimeProvider.now()
8584

8685
logger.d("Starting sync for items modified after $modifiedAfterGmt, max pages: $maxPages")
8786

@@ -94,63 +93,34 @@ class WooPosLocalCatalogSyncRepository @Inject constructor(
9493
return catalogSizeCheckResult.toPosLocalCatalogSyncFailure()
9594
}
9695

97-
val productSyncResult = syncProducts(site, modifiedAfterGmt, pageSize, maxPages)
98-
if (productSyncResult is WooPosSyncProductsResult.Failed) {
99-
return productSyncResult.toPosLocalCatalogSyncFailure()
96+
val syncResult = posSyncAction.syncCatalog(site, modifiedAfterGmt, pageSize, maxPages)
97+
if (syncResult is WooPosSyncResult.Failed) {
98+
return syncResult.toPosLocalCatalogSyncFailure()
10099
}
101100

102-
val variationSyncResult = syncVariations(site, modifiedAfterGmt, pageSize, maxPages)
103-
if (variationSyncResult is WooPosSyncVariationsResult.Failed) {
104-
return variationSyncResult.toPosLocalCatalogSyncFailure()
105-
}
106-
107-
val syncDuration = System.currentTimeMillis() - startTime
108-
109-
return PosLocalCatalogSyncResult.Success(
110-
productsSynced = (productSyncResult as WooPosSyncProductsResult.Success).productsSynced,
111-
variationsSynced = (variationSyncResult as WooPosSyncVariationsResult.Success).variationsSynced,
112-
syncDurationMs = syncDuration
113-
)
114-
}
101+
val successResult = syncResult as WooPosSyncResult.Success
115102

116-
private suspend fun syncProducts(
117-
site: SiteModel,
118-
modifiedAfterGmt: String?,
119-
pageSize: Int,
120-
maxPages: Int
121-
): WooPosSyncProductsResult {
122-
val result = posSyncAction.syncProducts(site, modifiedAfterGmt, pageSize, maxPages)
123-
124-
if (result is WooPosSyncProductsResult.Success) {
125-
result.serverDate?.let { serverDate ->
126-
syncTimestampManager.parseTimestampFromApi(serverDate)?.let { timestamp ->
127-
syncTimestampManager.storeProductsLastSyncTimestamp(timestamp)
128-
logger.d("Stored products sync timestamp: $serverDate")
129-
}
103+
successResult.productsServerDate?.let { serverDate ->
104+
syncTimestampManager.parseTimestampFromApi(serverDate)?.let { timestamp ->
105+
syncTimestampManager.storeProductsLastSyncTimestamp(timestamp)
106+
logger.d("Stored products sync timestamp: $serverDate")
130107
}
131108
}
132109

133-
return result
134-
}
135-
136-
private suspend fun syncVariations(
137-
site: SiteModel,
138-
modifiedAfterGmt: String?,
139-
pageSize: Int,
140-
maxPages: Int
141-
): WooPosSyncVariationsResult {
142-
val result = posSyncAction.syncVariations(site, modifiedAfterGmt, pageSize, maxPages)
143-
144-
if (result is WooPosSyncVariationsResult.Success) {
145-
result.serverDate?.let { serverDate ->
146-
syncTimestampManager.parseTimestampFromApi(serverDate)?.let { timestamp ->
147-
syncTimestampManager.storeVariationsLastSyncTimestamp(timestamp)
148-
logger.d("Stored variations sync timestamp: $serverDate")
149-
}
110+
successResult.variationsServerDate?.let { serverDate ->
111+
syncTimestampManager.parseTimestampFromApi(serverDate)?.let { timestamp ->
112+
syncTimestampManager.storeVariationsLastSyncTimestamp(timestamp)
113+
logger.d("Stored variations sync timestamp: $serverDate")
150114
}
151115
}
152116

153-
return result
117+
val syncDuration = dateTimeProvider.now() - startTime
118+
119+
return PosLocalCatalogSyncResult.Success(
120+
productsSynced = successResult.productsSynced,
121+
variationsSynced = successResult.variationsSynced,
122+
syncDurationMs = syncDuration
123+
)
154124
}
155125

156126
suspend fun getProductCount(site: SiteModel): Int =
@@ -160,34 +130,18 @@ class WooPosLocalCatalogSyncRepository @Inject constructor(
160130
posLocalCatalogStore.getVariationCount(LocalId(site.id)).getOrElse { 0 }
161131
}
162132

163-
private fun WooPosSyncProductsResult.Failed.toPosLocalCatalogSyncFailure(): PosLocalCatalogSyncResult.Failure {
164-
return when (this) {
165-
is WooPosSyncProductsResult.Failed.CatalogTooLarge -> {
166-
PosLocalCatalogSyncResult.Failure.CatalogTooLarge(
167-
error = "Product catalog too large: $totalPages pages exceed maximum of $maxPages pages",
168-
totalPages = totalPages,
169-
maxPages = maxPages
170-
)
171-
}
172-
173-
else -> {
174-
PosLocalCatalogSyncResult.Failure.UnexpectedError(error)
175-
}
176-
}
177-
}
178-
179-
private fun WooPosSyncVariationsResult.Failed.toPosLocalCatalogSyncFailure(): PosLocalCatalogSyncResult.Failure {
133+
private fun WooPosSyncResult.Failed.toPosLocalCatalogSyncFailure(): PosLocalCatalogSyncResult.Failure {
180134
return when (this) {
181-
is WooPosSyncVariationsResult.Failed.CatalogTooLarge -> {
135+
is WooPosSyncResult.Failed.CatalogTooLarge -> {
182136
PosLocalCatalogSyncResult.Failure.CatalogTooLarge(
183-
error = "Variations catalog too large: $totalPages pages exceed maximum of $maxPages pages",
137+
error = "Catalog too large: $totalPages pages exceed maximum of $maxPages pages",
184138
totalPages = totalPages,
185139
maxPages = maxPages
186140
)
187141
}
188142

189-
else -> {
190-
PosLocalCatalogSyncResult.Failure.UnexpectedError(error)
143+
is WooPosSyncResult.Failed.UnexpectedError -> {
144+
PosLocalCatalogSyncResult.Failure.UnexpectedError(errorMessage)
191145
}
192146
}
193147
}

0 commit comments

Comments
 (0)