diff --git a/Modules/Sources/Networking/Mapper/WooShippingConfigMapper.swift b/Modules/Sources/Networking/Mapper/WooShippingConfigMapper.swift index a9b39028c3e..8adef799d97 100644 --- a/Modules/Sources/Networking/Mapper/WooShippingConfigMapper.swift +++ b/Modules/Sources/Networking/Mapper/WooShippingConfigMapper.swift @@ -44,5 +44,10 @@ private struct WooShippingConfigMapperEnvelope: Decodable { extension WooShippingConfigMapper { /// Load only the relevant fields from remote /// - static let fieldsToLoad = "config.shipments, config.shippingLabelData.currentOrderLabels, config.shippingLabelData.storedData.selected_destination" + static let fieldsToLoad = [ + "config.shipments", + "config.shippingLabelData.currentOrderLabels", + "config.shippingLabelData.storedData.selected_destination", + "config.shippingLabelData.storedData.selected_origin" + ].joined(separator: ", ") } diff --git a/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingConfigResponse.swift b/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingConfigResponse.swift index 02b3b45d1cb..8c61279cb7d 100644 --- a/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingConfigResponse.swift +++ b/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingConfigResponse.swift @@ -79,8 +79,16 @@ public struct WooShippingLabelData: Decodable, Equatable { /// Inject destination addresses into labels if present let orderLabels: [ShippingLabel] - if let destinations = storedData?.selectedDestinations, !destinations.isEmpty { - orderLabels = WooShippingLabelData.mapDestinations(destinations, into: decodedOrderLabels) + + let destinations = storedData?.selectedDestinations + let origins = storedData?.selectedOrigins + + if destinations?.isEmpty == false || origins?.isEmpty == false { + orderLabels = WooShippingLabelData.mapAddresses( + origins: origins, + destinations: destinations, + into: decodedOrderLabels + ) } else { orderLabels = decodedOrderLabels } @@ -98,21 +106,27 @@ public struct WooShippingLabelData: Decodable, Equatable { } public extension WooShippingLabelData { - typealias WooShippingLabelDestinations = [String: WooShippingAddress] + typealias WooShippingLabelAddressMap = [String: WooShippingAddress] struct StoredData: Decodable, Equatable { - let selectedDestinations: WooShippingLabelDestinations? + let selectedDestinations: WooShippingLabelAddressMap? + let selectedOrigins: WooShippingLabelAddressMap? public enum CodingKeys: String, CodingKey { case selectedDestination = "selected_destination" + case selectedOrigin = "selected_origin" } public init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - self.selectedDestinations = try? container.decodeIfPresent( - WooShippingLabelDestinations.self, + selectedDestinations = try? container.decodeIfPresent( + WooShippingLabelAddressMap.self, forKey: CodingKeys.selectedDestination ) + selectedOrigins = try? container.decodeIfPresent( + WooShippingLabelAddressMap.self, + forKey: CodingKeys.selectedOrigin + ) } } } diff --git a/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingLabelData+mapDestinations.swift b/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingLabelData+mapDestinations.swift index 380ae9ee8b4..b857f7f77e0 100644 --- a/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingLabelData+mapDestinations.swift +++ b/Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingLabelData+mapDestinations.swift @@ -1,21 +1,24 @@ import Foundation extension WooShippingLabelData { - static func mapDestinations( - _ destinations: WooShippingLabelDestinations, + static func mapAddresses( + origins: WooShippingLabelAddressMap?, + destinations: WooShippingLabelAddressMap?, into labels: [ShippingLabel] ) -> [ShippingLabel] { return labels.map { label in - guard - let shipmentID = label.shipmentID, - let destinationAddress = destinations[ - WooShippingShipmentIDFormatter.formattedShipmentID(shipmentID) - ] ?? destinations[shipmentID] /// Fallback for ids previously submitted without `shipment_` formatting - else { + guard let shipmentID = label.shipmentID else { return label } - return label.copy(destinationAddress: destinationAddress.toShippingLabelAddress()) + let formattedID = WooShippingShipmentIDFormatter.formattedShipmentID(shipmentID) + let originAddress = origins?[formattedID] ?? origins?[shipmentID] + let destinationAddress = destinations?[formattedID] ?? destinations?[shipmentID] + + return label.copy( + originAddress: originAddress?.toShippingLabelAddress() ?? .copy, + destinationAddress: destinationAddress?.toShippingLabelAddress() ?? .copy + ) } } } diff --git a/Modules/Tests/NetworkingTests/Remote/WooShippingRemoteTests.swift b/Modules/Tests/NetworkingTests/Remote/WooShippingRemoteTests.swift index 52eb73aaada..51c4fd1ae52 100644 --- a/Modules/Tests/NetworkingTests/Remote/WooShippingRemoteTests.swift +++ b/Modules/Tests/NetworkingTests/Remote/WooShippingRemoteTests.swift @@ -857,10 +857,10 @@ final class WooShippingRemoteTests: XCTestCase { // MARK: - Load Config With Destinations - func test_loadConfig_withDestinations_parses_success_response() throws { + func test_load_config_with_addresses_parses_success_response() throws { // Given let remote = WooShippingRemote(network: network) - network.simulateResponse(requestUrlSuffix: "config/label-purchase/\(sampleOrderID)", filename: "wooshipping-config-with-destinations") + network.simulateResponse(requestUrlSuffix: "config/label-purchase/\(sampleOrderID)", filename: "wooshipping-config-with-addresses") // When let result: Result = waitFor { promise in @@ -874,12 +874,14 @@ final class WooShippingRemoteTests: XCTestCase { let label = try XCTUnwrap(config.shippingLabelData?.currentOrderLabels.first) XCTAssertNotNil(label.destinationAddress) XCTAssertEqual(label.destinationAddress.address1, "200 N SPRING ST") + XCTAssertNotNil(label.originAddress) + XCTAssertEqual(label.originAddress.address1, "Test origin address line") } - func test_loadConfig_withoutDestinations_parses_success_response() throws { + func test_load_config_without_addresses_parses_success_response() throws { // Given let remote = WooShippingRemote(network: network) - network.simulateResponse(requestUrlSuffix: "config/label-purchase/\(sampleOrderID)", filename: "wooshipping-config-without-destinations") + network.simulateResponse(requestUrlSuffix: "config/label-purchase/\(sampleOrderID)", filename: "wooshipping-config-without-addresses") // When let result: Result = waitFor { promise in @@ -892,12 +894,13 @@ final class WooShippingRemoteTests: XCTestCase { let config = try XCTUnwrap(result.get()) let label = try XCTUnwrap(config.shippingLabelData?.currentOrderLabels.first) XCTAssertTrue(label.destinationAddress.isEmpty) + XCTAssertTrue(label.originAddress.isEmpty) } - func test_loadConfig_withInvalidDestinations_parses_success_response() throws { + func test_load_config_with_invalid_addresses_parses_success_response() throws { // Given let remote = WooShippingRemote(network: network) - network.simulateResponse(requestUrlSuffix: "config/label-purchase/\(sampleOrderID)", filename: "wooshipping-config-with-invalid-destinations") + network.simulateResponse(requestUrlSuffix: "config/label-purchase/\(sampleOrderID)", filename: "wooshipping-config-with-invalid-addresses") // When let result: Result = waitFor { promise in @@ -910,6 +913,7 @@ final class WooShippingRemoteTests: XCTestCase { let config = try XCTUnwrap(result.get()) let label = try XCTUnwrap(config.shippingLabelData?.currentOrderLabels.first) XCTAssertTrue(label.destinationAddress.isEmpty) + XCTAssertTrue(label.originAddress.isEmpty) } // MARK: Update shipment diff --git a/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-destinations.json b/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-addresses.json similarity index 79% rename from Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-destinations.json rename to Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-addresses.json index 11d0a18d215..4beac8c7193 100644 --- a/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-destinations.json +++ b/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-addresses.json @@ -11,6 +11,15 @@ "postcode": "90012-4801", "country": "US" } + }, + "selected_origin": { + "shipment_1": { + "address_1": "Test origin address line", + "city": "Test origin city", + "state": "CA", + "postcode": "90012-4801", + "country": "US" + } } }, "currentOrderLabels": [ diff --git a/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-invalid-destinations.json b/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-invalid-addresses.json similarity index 87% rename from Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-invalid-destinations.json rename to Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-invalid-addresses.json index a73c78d8818..6d55ac02061 100644 --- a/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-invalid-destinations.json +++ b/Modules/Tests/NetworkingTests/Responses/wooshipping-config-with-invalid-addresses.json @@ -7,6 +7,11 @@ { "address_1": "200 N SPRING ST" } + ], + "selected_origin": [ + { + "address_1": "Test origin address line" + } ] }, "currentOrderLabels": [ diff --git a/Modules/Tests/NetworkingTests/Responses/wooshipping-config-without-destinations.json b/Modules/Tests/NetworkingTests/Responses/wooshipping-config-without-addresses.json similarity index 100% rename from Modules/Tests/NetworkingTests/Responses/wooshipping-config-without-destinations.json rename to Modules/Tests/NetworkingTests/Responses/wooshipping-config-without-addresses.json diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 8942c70cd91..b34ce427211 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -7,7 +7,7 @@ 22.7 ----- -- [*] Shipping Labels: Fixed an issue where the destination address was missing for previously purchased shipping labels. [https://github.com/woocommerce/woocommerce-ios/pull/15866] +- [*] Shipping Labels: Fixed an issue where the origin and destination addresses were missing for previously purchased shipping labels. [https://github.com/woocommerce/woocommerce-ios/pull/15866] - [*] Shipping Labels: Fixed an issue where the purchase button would display a stale price after changing the origin address. [https://github.com/woocommerce/woocommerce-ios/pull/15795] - [*] Order Details: Fix crash when reloading data [https://github.com/woocommerce/woocommerce-ios/pull/15764] - [*] Shipping Labels: Improved shipment management UI by hiding remove/merge options instead of disabling them, hiding merge option for orders with 2 or fewer unfulfilled shipments, and hiding the ellipsis menu when no remove/merge actions are available [https://github.com/woocommerce/woocommerce-ios/pull/15760] diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsView.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsView.swift index 383d3397404..bf6a3c03096 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsView.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsView.swift @@ -374,10 +374,15 @@ private extension WooShippingCreateLabelsView { Text(Localization.BottomSheet.shipFrom) .trackSize(size: $shipmentDetailsShipFromSize) - if viewModel.canViewLabel, - let addressLines = viewModel.originAddressLines { - AddressLinesView(addressLines: addressLines) - .frame(maxWidth: .infinity, alignment: .leading) + if viewModel.canViewLabel { + Group { + if let addressLines = viewModel.originAddressLines { + AddressLinesView(addressLines: addressLines) + } else { + Spacer() + } + } + .frame(maxWidth: .infinity, alignment: .leading) } else { VStack(alignment: .leading) { Button {