Skip to content

Commit 98d5703

Browse files
committed
Merge branch 'trunk' into issue/WOOMOB-887-cache-carrier-packages-data
# Conflicts: # libs/fluxc-plugin/schemas/org.wordpress.android.fluxc.persistence.WCAndroidDatabase/61.json # libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/WCAndroidDatabase.kt
2 parents 5e13f7f + c5eddf4 commit 98d5703

File tree

23 files changed

+8651
-142
lines changed

23 files changed

+8651
-142
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Auto-merge Dependabot PATCH updates
2+
3+
on:
4+
pull_request:
5+
types: [opened, reopened]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
11+
jobs:
12+
auto-merge:
13+
runs-on: ubuntu-latest
14+
if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'woocommerce/woocommerce-android'
15+
env:
16+
PR_URL: ${{ github.event.pull_request.html_url }}
17+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
steps:
19+
- uses: actions/checkout@v5
20+
21+
- name: Fetch Dependabot metadata
22+
id: metadata
23+
uses: dependabot/fetch-metadata@v2
24+
with:
25+
github-token: "${{ secrets.GITHUB_TOKEN }}"
26+
27+
- name: Assign closest open milestone to PR
28+
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
29+
run: |
30+
set -e
31+
number=$(gh api repos/$GITHUB_REPOSITORY/milestones \
32+
--jq '[.[]
33+
| select(.state=="open" and .due_on!=null and (.due_on | fromdateiso8601) >= now)
34+
]
35+
| sort_by(.due_on)
36+
| .[0].number')
37+
38+
if [ -n "$number" ]; then
39+
echo "Assigning milestone #$number to PR #${{ github.event.pull_request.number }}"
40+
gh pr edit "${{ github.event.pull_request.number }}" --milestone "$number"
41+
else
42+
echo "No future open milestones found."
43+
fi
44+
45+
- name: Approve the PR
46+
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
47+
run: |
48+
set -e
49+
gh pr review --approve "$PR_URL"
50+
51+
- name: Enable auto-merge for Dependabot PRs
52+
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
53+
run: |
54+
set -e
55+
gh pr merge --auto --merge "$PR_URL"

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- [*] Shipping Labels: Adds caching to the "Select a Package" screen [https://github.com/woocommerce/woocommerce-android/pull/14541]
1616
- [*] Add more filter options to orders filters sales channel [https://github.com/woocommerce/woocommerce-android/pull/14546]
1717
- [*] Automatically populate the weight field in the create shipment flow [https://github.com/woocommerce/woocommerce-android/pull/14525]
18+
- [*] [Shipping Labels] Fixed displaying incorrect hazardous material option for purchased labels [https://github.com/woocommerce/woocommerce-android/pull/14571]
1819

1920
23.1
2021
-----

WooCommerce/src/main/kotlin/com/woocommerce/android/model/ShippingLabel.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.woocommerce.android.model
22

33
import android.os.Parcelable
4+
import com.woocommerce.android.ui.orders.shippinglabels.creation.ShippingLabelHazmatCategory
45
import com.woocommerce.android.ui.orders.wooshippinglabels.models.ShippingLabelModel
56
import com.woocommerce.android.ui.orders.wooshippinglabels.models.ShippingLabelStatus
67
import kotlinx.parcelize.IgnoredOnParcel
@@ -25,6 +26,7 @@ data class ShippingLabel(
2526
val currency: String = "",
2627
val productNames: List<String> = emptyList(),
2728
val productIds: List<Long> = emptyList(),
29+
val hazmatCategory: ShippingLabelHazmatCategory? = null,
2830
val originAddress: Address? = null,
2931
val destinationAddress: Address? = null,
3032
val refund: Refund? = null,
@@ -96,6 +98,7 @@ fun ShippingLabel.toShippingLabelModel(): ShippingLabelModel {
9698
usedDate = null,
9799
refund = refund?.let { ShippingLabelModel.Refund(status = it.status, requestDate = it.refundDate) },
98100
products = products,
101+
hazmatCategory = hazmatCategory,
99102
originAddress = originAddress,
100103
destinationAddress = destinationAddress
101104
)

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ class WooShippingLabelCreationViewModel @Inject constructor(
183183

184184
init {
185185
launch { observeShippingLabelInformation() }
186+
launch { getHazmatSelection() }
186187
launch { getDestinationAddress() }
187188
launch { trackScreenShownEvent() }
188189
launch { getSavedShipments() }
@@ -323,6 +324,14 @@ class WooShippingLabelCreationViewModel @Inject constructor(
323324
}
324325
}
325326

327+
private suspend fun getHazmatSelection() {
328+
shipments.filter { it.isNotEmpty() }.first().let { shipmentList ->
329+
hazmatStatesFlow.value = shipmentList.map { shipment ->
330+
shipment.label?.hazmatCategory?.let { Declared(it) } ?: NoSelection
331+
}
332+
}
333+
}
334+
326335
private suspend fun getDestinationAddress() {
327336
combine(
328337
order.drop(1),

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/models/ShippingLabelModel.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.woocommerce.android.model.Address
66
import com.woocommerce.android.model.Order
77
import com.woocommerce.android.model.ShippingLabel
88
import com.woocommerce.android.ui.orders.shippinglabels.ShipmentTrackingUrls
9+
import com.woocommerce.android.ui.orders.shippinglabels.creation.ShippingLabelHazmatCategory
910
import com.woocommerce.android.ui.orders.wooshippinglabels.rates.datasource.WooShippingRatesDatasourceMapper.Companion.CARRIER_DHL_EXPRESS_KEY
1011
import kotlinx.parcelize.IgnoredOnParcel
1112
import kotlinx.parcelize.Parcelize
@@ -38,6 +39,7 @@ data class ShippingLabelModel(
3839
val usedDate: Long?,
3940
val refund: Refund?,
4041
val products: List<Order.Item> = emptyList(),
42+
val hazmatCategory: ShippingLabelHazmatCategory? = null,
4143
val originAddress: Address? = null,
4244
val destinationAddress: Address? = null,
4345
val error: String? = null,

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/networking/DTOs.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ data class ShippingLabelDataDTO(
9595
)
9696

9797
data class StoredDataDTO(
98+
@SerializedName("selected_hazmat")
99+
@JsonAdapter(MapOrEmptyMapDeserializer::class)
100+
val selectedHazmat: Map<String, HazmatDTO>,
98101
@SerializedName("selected_origin")
99102
@JsonAdapter(MapOrEmptyMapDeserializer::class)
100103
val selectedOrigin: Map<String, OriginAddressDTO>,

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/networking/WooShippingLabelRepository.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,15 @@ class WooShippingLabelRepository @Inject constructor(
118118
labelId = labelId,
119119
).also {
120120
it.result?.shippingLabel?.let { labelDTO ->
121-
// The API doesn't return the origin and destination addresses,
121+
// The API doesn't return the hazmat category, origin and destination addresses,
122122
// we get it from the already cached labels in the database after the purchase request
123123
val currentLabel = wooShippingDao.getLabel(
124124
selectedSite.get().localId(),
125125
LocalOrRemoteId.RemoteId(orderId),
126126
labelId
127127
)
128128
val updatedLabel = mapper(labelDTO, site, orderId).copy(
129+
hazmatCategory = currentLabel?.hazmatCategory,
129130
originAddress = currentLabel?.originAddress,
130131
destinationAddress = currentLabel?.destinationAddress
131132
)

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/networking/WooShippingNetworkingMapper.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class WooShippingNetworkingMapper @Inject constructor(
136136
requestDate = refund.requestDate?.let { Date(it) }
137137
)
138138
},
139+
hazmatCategory = null,
139140
originAddress = null,
140141
destinationAddress = null,
141142
)
@@ -150,6 +151,7 @@ class WooShippingNetworkingMapper @Inject constructor(
150151

151152
return shippingLabelData.currentOrderLabels?.map { shippingLabelDTO ->
152153
val shipmentKey = shippingLabelDTO.shipmentId?.let { key(it) }
154+
val hazmatCategory = shippingLabelData.storedData?.selectedHazmat?.get(shipmentKey)?.category
153155
val originAddress = shippingLabelData.storedData?.selectedOrigin?.get(shipmentKey)?.let {
154156
WooShippingLabelEntity.Address(
155157
company = it.company,
@@ -180,6 +182,7 @@ class WooShippingNetworkingMapper @Inject constructor(
180182
}
181183

182184
invoke(shippingLabelDTO, site, orderId).copy(
185+
hazmatCategory = hazmatCategory,
183186
originAddress = originAddress,
184187
destinationAddress = destinationAddress
185188
)
@@ -195,6 +198,7 @@ class WooShippingNetworkingMapper @Inject constructor(
195198

196199
return purchasedShippingLabelResponseDTO.labels.map { shippingLabelDTO ->
197200
val shipmentKey = shippingLabelDTO.shipmentId?.let { key(it) }
201+
val hazmatCategory = purchasedShippingLabelResponseDTO.selectedHazmat[shipmentKey]?.category
198202
val originAddress = purchasedShippingLabelResponseDTO.selectedOrigin[shipmentKey]?.let {
199203
WooShippingLabelEntity.Address(
200204
company = it.company,
@@ -225,6 +229,7 @@ class WooShippingNetworkingMapper @Inject constructor(
225229
}
226230

227231
invoke(shippingLabelDTO, site, orderId).copy(
232+
hazmatCategory = hazmatCategory,
228233
originAddress = originAddress,
229234
destinationAddress = destinationAddress
230235
)
@@ -257,6 +262,9 @@ class WooShippingNetworkingMapper @Inject constructor(
257262
refund = labelEntity.refund?.let { refund ->
258263
ShippingLabelModel.Refund(status = refund.status, requestDate = refund.requestDate)
259264
},
265+
hazmatCategory = labelEntity.hazmatCategory?.takeUnless { it.isEmpty() }?.let {
266+
runCatching { ShippingLabelHazmatCategory.valueOf(it) }.getOrNull()
267+
},
260268
originAddress = labelEntity.originAddress?.let { invoke(it) },
261269
destinationAddress = labelEntity.destinationAddress?.let { invoke(it) }
262270
)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package com.woocommerce.android.ui.woopos.common.data.models
2+
3+
import android.os.Parcelable
4+
import kotlinx.parcelize.Parcelize
5+
import java.math.BigDecimal
6+
7+
/**
8+
* This model provides a clean separation between the data layer (WCPosProductEntity)
9+
* and the view layer, ensuring all required data is present and properly typed.
10+
*/
11+
@Parcelize
12+
data class WooPosProductModelVersion2(
13+
val remoteId: Long,
14+
val parentId: Long?,
15+
val name: String,
16+
val sku: String,
17+
val globalUniqueId: String,
18+
val type: WooPosProductType,
19+
val status: WooPosProductStatus,
20+
val pricing: WooPosPricing,
21+
val description: String,
22+
val shortDescription: String,
23+
val isDownloadable: Boolean,
24+
val lastModified: String,
25+
val images: List<WooPosProductImage> = emptyList(),
26+
val attributes: List<WooPosProductAttribute> = emptyList(),
27+
val categories: List<WooPosProductCategory> = emptyList(),
28+
val tags: List<WooPosProductTag> = emptyList(),
29+
) : Parcelable {
30+
31+
sealed class WooPosPricing : Parcelable {
32+
@Parcelize
33+
data object NoPricing : WooPosPricing()
34+
35+
@Parcelize
36+
data class RegularPricing(
37+
val price: BigDecimal
38+
) : WooPosPricing()
39+
40+
@Parcelize
41+
data class SalePricing(
42+
val regularPrice: BigDecimal,
43+
val salePrice: BigDecimal
44+
) : WooPosPricing()
45+
46+
val displayPrice: BigDecimal?
47+
get() = when (this) {
48+
is NoPricing -> null
49+
is RegularPricing -> price
50+
is SalePricing -> salePrice
51+
}
52+
53+
val isOnSale: Boolean
54+
get() = this is SalePricing
55+
56+
val hasPrice: Boolean
57+
get() = this != NoPricing
58+
59+
val formattedPrice: String
60+
get() = displayPrice?.toPlainString() ?: ""
61+
}
62+
63+
enum class WooPosProductType {
64+
SIMPLE,
65+
VARIABLE,
66+
GROUPED,
67+
EXTERNAL,
68+
VARIATION,
69+
SUBSCRIPTION,
70+
VARIABLE_SUBSCRIPTION,
71+
CUSTOM,
72+
BUNDLE,
73+
COMPOSITE
74+
}
75+
76+
enum class WooPosProductStatus {
77+
PUBLISH,
78+
DRAFT,
79+
PENDING,
80+
PRIVATE,
81+
TRASH,
82+
UNKNOWN
83+
}
84+
85+
@Parcelize
86+
data class WooPosProductImage(
87+
val id: Long,
88+
val url: String,
89+
val name: String,
90+
val alt: String?
91+
) : Parcelable
92+
93+
@Parcelize
94+
data class WooPosProductAttribute(
95+
val id: Long,
96+
val name: String,
97+
val options: List<String>,
98+
val isVisible: Boolean,
99+
val isVariation: Boolean
100+
) : Parcelable
101+
102+
@Parcelize
103+
data class WooPosProductCategory(
104+
val id: Long,
105+
val name: String,
106+
val slug: String
107+
) : Parcelable
108+
109+
@Parcelize
110+
data class WooPosProductTag(
111+
val id: Long,
112+
val name: String,
113+
val slug: String
114+
) : Parcelable
115+
116+
val firstImageUrl: String?
117+
get() = images.firstOrNull()?.url
118+
}

0 commit comments

Comments
 (0)