Skip to content

Commit 5358b2b

Browse files
authored
Shipping Labels: Add new Networking type for WooShipping shipments (#15885)
2 parents ba1747e + cc35a03 commit 5358b2b

File tree

16 files changed

+378
-169
lines changed

16 files changed

+378
-169
lines changed

Modules/Sources/Fakes/Networking.generated.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,19 @@ extension Networking.WooShippingSelectedRate {
24832483
)
24842484
}
24852485
}
2486+
extension Networking.WooShippingShipment {
2487+
/// Returns a "ready to use" type filled with fake values.
2488+
///
2489+
public static func fake() -> Networking.WooShippingShipment {
2490+
.init(
2491+
siteID: .fake(),
2492+
orderID: .fake(),
2493+
index: .fake(),
2494+
items: .fake(),
2495+
shippingLabel: .fake()
2496+
)
2497+
}
2498+
}
24862499
extension Networking.WooShippingShipmentItem {
24872500
/// Returns a "ready to use" type filled with fake values.
24882501
///

Modules/Sources/Networking/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3481,7 +3481,7 @@ extension Networking.WooShippingAddress {
34813481
extension Networking.WooShippingConfig {
34823482
public func copy(
34833483
siteID: CopiableProp<Int64> = .copy,
3484-
shipments: CopiableProp<[String: [WooShippingShipmentItem]]> = .copy,
3484+
shipments: CopiableProp<[WooShippingShipment]> = .copy,
34853485
shippingLabelData: NullableCopiableProp<WooShippingLabelData> = .copy
34863486
) -> Networking.WooShippingConfig {
34873487
let siteID = siteID ?? self.siteID
@@ -3724,6 +3724,30 @@ extension Networking.WooShippingPackagesResponse {
37243724
}
37253725
}
37263726

3727+
extension Networking.WooShippingShipment {
3728+
public func copy(
3729+
siteID: CopiableProp<Int64> = .copy,
3730+
orderID: CopiableProp<Int64> = .copy,
3731+
index: CopiableProp<String> = .copy,
3732+
items: CopiableProp<[WooShippingShipmentItem]> = .copy,
3733+
shippingLabel: NullableCopiableProp<ShippingLabel> = .copy
3734+
) -> Networking.WooShippingShipment {
3735+
let siteID = siteID ?? self.siteID
3736+
let orderID = orderID ?? self.orderID
3737+
let index = index ?? self.index
3738+
let items = items ?? self.items
3739+
let shippingLabel = shippingLabel ?? self.shippingLabel
3740+
3741+
return Networking.WooShippingShipment(
3742+
siteID: siteID,
3743+
orderID: orderID,
3744+
index: index,
3745+
items: items,
3746+
shippingLabel: shippingLabel
3747+
)
3748+
}
3749+
}
3750+
37273751
extension Networking.WooShippingShipmentItem {
37283752
public func copy(
37293753
id: CopiableProp<Int64> = .copy,

Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingConfigResponse.swift

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ public struct WooShippingConfig: Decodable, Equatable, GeneratedFakeable, Genera
1515
/// The remote ID of the site that owns this shipping label config info.
1616
public let siteID: Int64
1717

18-
/// Shipments of this order. The keys are the ids of the shipment.
19-
public let shipments: WooShippingShipments
18+
/// Shipments of this order.
19+
public let shipments: [WooShippingShipment]
2020

2121
/// Holds info about the shipping labels
2222
public let shippingLabelData: WooShippingLabelData?
2323

2424
public init(siteID: Int64,
25-
shipments: WooShippingShipments,
25+
shipments: [WooShippingShipment],
2626
shippingLabelData: WooShippingLabelData?) {
2727
self.siteID = siteID
2828
self.shipments = shipments
@@ -39,17 +39,46 @@ public struct WooShippingConfig: Decodable, Equatable, GeneratedFakeable, Genera
3939
throw WooShippingConfigDecodingError.missingSiteID
4040
}
4141

42+
guard let orderID = decoder.userInfo[.orderID] as? Int64 else {
43+
throw WooShippingConfigDecodingError.missingOrderID
44+
}
45+
4246
let container = try decoder.container(keyedBy: CodingKeys.self)
43-
let shipments: WooShippingShipments = {
47+
let shippingLabelData = try container.decodeIfPresent(WooShippingLabelData.self, forKey: .shippingLabelData)
48+
49+
let shipments: [WooShippingShipment] = {
4450
guard let shipmentsString = try? container.decodeIfPresent(String.self, forKey: .shipments),
4551
let data = shipmentsString.data(using: .utf8) else {
46-
return [:]
52+
return []
4753
}
4854

49-
return (try? JSONDecoder().decode(WooShippingShipments.self, from: data)) ?? [:]
55+
guard let contents = (try? JSONDecoder().decode(WooShippingShipments.self, from: data)) else {
56+
return []
57+
}
58+
59+
let labels = shippingLabelData?.currentOrderLabels ?? []
60+
var shipments = [WooShippingShipment]()
61+
for (index, items) in contents {
62+
let label: ShippingLabel? = {
63+
let purchasedLabels = labels.filter {
64+
$0.shipmentID == index && $0.status == .purchased
65+
}
66+
let sortedLabels = purchasedLabels.sorted { $0.dateCreated > $1.dateCreated }
67+
if let completedLabel = sortedLabels.first(where: { $0.refund == nil }) {
68+
return completedLabel
69+
} else {
70+
return sortedLabels.first
71+
}
72+
}()
73+
shipments.append(WooShippingShipment(siteID: siteID,
74+
orderID: orderID,
75+
index: index,
76+
items: items,
77+
shippingLabel: label))
78+
}
79+
return shipments
5080
}()
5181

52-
let shippingLabelData = try container.decodeIfPresent(WooShippingLabelData.self, forKey: .shippingLabelData)
5382
self.init(siteID: siteID,
5483
shipments: shipments,
5584
shippingLabelData: shippingLabelData)
@@ -135,4 +164,5 @@ public extension WooShippingLabelData {
135164
//
136165
enum WooShippingConfigDecodingError: Error {
137166
case missingSiteID
167+
case missingOrderID
138168
}

Modules/Sources/Networking/Model/ShippingLabel/Shipments/WooShippingShipmentItem.swift

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
11
import Foundation
22
import Codegen
3-
import WooFoundation
43

5-
/// Represents a shipment in Shipping Labels for the WooCommerce Shipping extension.
4+
/// Represents a shipment from the WooCommerce Shipping extension.
5+
///
6+
public struct WooShippingShipment: Equatable, GeneratedFakeable, GeneratedCopiable {
7+
/// ID of the site that the shipment belongs to.
8+
public let siteID: Int64
9+
10+
/// ID of the order that the shipment belongs to.
11+
public let orderID: Int64
12+
13+
/// Index of the shipment.
14+
/// The expected format is a numeric string, e.g: "0", "1", etc.
15+
public let index: String
16+
17+
/// Contents of the shipment
18+
public let items: [WooShippingShipmentItem]
19+
20+
/// The latest label purchased for the shipment
21+
public let shippingLabel: ShippingLabel?
22+
23+
public init(siteID: Int64,
24+
orderID: Int64,
25+
index: String,
26+
items: [WooShippingShipmentItem],
27+
shippingLabel: ShippingLabel?) {
28+
self.siteID = siteID
29+
self.orderID = orderID
30+
self.index = index
31+
self.items = items
32+
self.shippingLabel = shippingLabel
33+
}
34+
}
35+
36+
/// Represents a shipment item from the WooCommerce Shipping extension.
637
///
738
public struct WooShippingShipmentItem: Codable, Equatable, GeneratedFakeable, GeneratedCopiable {
839
/// ID of the shipment

Modules/Sources/Yosemite/Model/Model.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ public typealias WooShippingDestinationAddressUpdate = Networking.WooShippingDes
200200
public typealias WooShippingConfig = Networking.WooShippingConfig
201201
public typealias WooShippingUpdateShipment = Networking.WooShippingUpdateShipment
202202
public typealias WooShippingShipmentItem = Networking.WooShippingShipmentItem
203+
public typealias WooShippingShipment = Networking.WooShippingShipment
203204
public typealias WooShippingShipments = Networking.WooShippingShipments
204205
public typealias WooShippingSelectedRate = Networking.WooShippingSelectedRate
205206
public typealias WPComPlan = Networking.WPComPlan

Modules/Tests/NetworkingTests/Mapper/WooShippingConfigMapperTests.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,21 @@ final class WooShippingConfigMapperTests: XCTestCase {
1515
}
1616

1717
XCTAssertEqual(config.shipments.count, 3)
18+
let shipment0 = try XCTUnwrap(config.shipments.first(where: { $0.index == "0" }))
19+
XCTAssertNil(shipment0.shippingLabel) // non-purchased status means no label found
20+
XCTAssertEqual(shipment0.items.count, 1)
21+
22+
let shipment1 = try XCTUnwrap(config.shipments.first(where: { $0.index == "1" }))
23+
XCTAssertEqual(shipment1.shippingLabel?.shippingLabelID, 4871)
24+
XCTAssertEqual(shipment1.items.count, 1)
25+
26+
let shipment2 = try XCTUnwrap(config.shipments.first(where: { $0.index == "2" }))
27+
XCTAssertEqual(shipment2.shippingLabel?.shippingLabelID, 4873)
28+
XCTAssertNotNil(shipment2.shippingLabel?.refund)
29+
XCTAssertEqual(shipment2.items.count, 1)
30+
1831
let shippingLabelData = try XCTUnwrap(config.shippingLabelData?.currentOrderLabels)
19-
XCTAssertEqual(shippingLabelData.count, 1)
32+
XCTAssertEqual(shippingLabelData.count, 3)
2033
XCTAssertEqual(shippingLabelData.first?.shipmentID, "1")
2134
XCTAssertEqual(shippingLabelData.first?.shippingLabelID, 4871)
2235
}
@@ -28,8 +41,22 @@ final class WooShippingConfigMapperTests: XCTestCase {
2841
}
2942

3043
XCTAssertEqual(config.shipments.count, 3)
44+
let shipment0 = try XCTUnwrap(config.shipments.first(where: { $0.index == "0" }))
45+
XCTAssertNil(shipment0.shippingLabel) // non-purchased status means no label found
46+
XCTAssertEqual(shipment0.items.count, 1)
47+
48+
let shipment1 = try XCTUnwrap(config.shipments.first(where: { $0.index == "1" }))
49+
XCTAssertEqual(shipment1.shippingLabel?.shippingLabelID, 4871)
50+
XCTAssertNil(shipment1.shippingLabel?.refund)
51+
XCTAssertEqual(shipment1.items.count, 1)
52+
53+
let shipment2 = try XCTUnwrap(config.shipments.first(where: { $0.index == "2" }))
54+
XCTAssertEqual(shipment2.shippingLabel?.shippingLabelID, 4873)
55+
XCTAssertNotNil(shipment2.shippingLabel?.refund)
56+
XCTAssertEqual(shipment2.items.count, 1)
57+
3158
let shippingLabelData = try XCTUnwrap(config.shippingLabelData?.currentOrderLabels)
32-
XCTAssertEqual(shippingLabelData.count, 1)
59+
XCTAssertEqual(shippingLabelData.count, 3)
3360
XCTAssertEqual(shippingLabelData.first?.shipmentID, "1")
3461
XCTAssertEqual(shippingLabelData.first?.shippingLabelID, 4871)
3562
}

Modules/Tests/NetworkingTests/Responses/shipping-label-config-success-without-data.json

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"created": 1742292110723,
1010
"carrier_id": "usps",
1111
"service_name": "USPS - Priority Mail",
12-
"status": "PURCHASE_IN_PROGRESS",
12+
"status": "PURCHASED",
1313
"commercial_invoice_url": "",
1414
"is_commercial_invoice_submitted_electronically": false,
1515
"package_name": "Small Flat Rate Box",
@@ -23,6 +23,55 @@
2323
"id": "1",
2424
"receipt_item_id": -1,
2525
"created_date": 1742292110000
26+
},
27+
{
28+
"label_id": 4872,
29+
"tracking": null,
30+
"refundable_amount": 0,
31+
"created": 1742292110723,
32+
"carrier_id": "usps",
33+
"service_name": "USPS - Priority Mail",
34+
"status": "PURCHASE_ERROR",
35+
"commercial_invoice_url": "",
36+
"is_commercial_invoice_submitted_electronically": false,
37+
"package_name": "Small Flat Rate Box",
38+
"is_letter": false,
39+
"product_names": [
40+
"BG upload"
41+
],
42+
"product_ids": [
43+
522
44+
],
45+
"id": "0",
46+
"receipt_item_id": -1,
47+
"created_date": 1742292110000
48+
},
49+
{
50+
"label_id": 4873,
51+
"tracking": null,
52+
"refundable_amount": 0,
53+
"created": 1742292110723,
54+
"carrier_id": "usps",
55+
"service_name": "USPS - Priority Mail",
56+
"status": "PURCHASED",
57+
"commercial_invoice_url": "",
58+
"is_commercial_invoice_submitted_electronically": false,
59+
"package_name": "Small Flat Rate Box",
60+
"is_letter": false,
61+
"product_names": [
62+
"BG upload"
63+
],
64+
"product_ids": [
65+
522
66+
],
67+
"refund": {
68+
"request_date": 1603715617000,
69+
"status": "pending",
70+
"refund_date": 1
71+
},
72+
"id": "2",
73+
"receipt_item_id": -1,
74+
"created_date": 1742292110000
2675
}
2776
]
2877
},

Modules/Tests/NetworkingTests/Responses/shipping-label-config-success.json

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"created": 1742292110723,
1111
"carrier_id": "usps",
1212
"service_name": "USPS - Priority Mail",
13-
"status": "PURCHASE_IN_PROGRESS",
13+
"status": "PURCHASED",
1414
"commercial_invoice_url": "",
1515
"is_commercial_invoice_submitted_electronically": false,
1616
"package_name": "Small Flat Rate Box",
@@ -24,6 +24,55 @@
2424
"id": "1",
2525
"receipt_item_id": -1,
2626
"created_date": 1742292110000
27+
},
28+
{
29+
"label_id": 4872,
30+
"tracking": null,
31+
"refundable_amount": 0,
32+
"created": 1742292110723,
33+
"carrier_id": "usps",
34+
"service_name": "USPS - Priority Mail",
35+
"status": "PURCHASE_ERROR",
36+
"commercial_invoice_url": "",
37+
"is_commercial_invoice_submitted_electronically": false,
38+
"package_name": "Small Flat Rate Box",
39+
"is_letter": false,
40+
"product_names": [
41+
"BG upload"
42+
],
43+
"product_ids": [
44+
522
45+
],
46+
"id": "0",
47+
"receipt_item_id": -1,
48+
"created_date": 1742292110000
49+
},
50+
{
51+
"label_id": 4873,
52+
"tracking": null,
53+
"refundable_amount": 0,
54+
"created": 1742292110723,
55+
"carrier_id": "usps",
56+
"service_name": "USPS - Priority Mail",
57+
"status": "PURCHASED",
58+
"commercial_invoice_url": "",
59+
"is_commercial_invoice_submitted_electronically": false,
60+
"package_name": "Small Flat Rate Box",
61+
"is_letter": false,
62+
"product_names": [
63+
"BG upload"
64+
],
65+
"product_ids": [
66+
522
67+
],
68+
"refund": {
69+
"request_date": 1603715617000,
70+
"status": "pending",
71+
"refund_date": 1
72+
},
73+
"id": "2",
74+
"receipt_item_id": -1,
75+
"created_date": 1742292110000
2776
}
2877
]
2978
},

Modules/Tests/YosemiteTests/Stores/WooShippingStoreTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ final class WooShippingStoreTests: XCTestCase {
996996
func test_loadConfig_returns_success_response() throws {
997997
// Given
998998
let remote = MockWooShippingRemote()
999-
let expectedConfig = WooShippingConfig.fake().copy(shipments: ["0": [WooShippingShipmentItem.fake()]])
999+
let expectedConfig = WooShippingConfig.fake().copy(shipments: [WooShippingShipment.fake()])
10001000
remote.whenLoadingConfig(siteID: sampleSiteID, thenReturn: .success(expectedConfig))
10011001
let store = WooShippingStore(dispatcher: dispatcher, storageManager: storageManager, network: network, remote: remote)
10021002

@@ -1084,7 +1084,7 @@ final class WooShippingStoreTests: XCTestCase {
10841084
expiryDate: nil)
10851085
}()
10861086
let expectedResponse = WooShippingConfig.fake().copy(
1087-
shipments: ["0": [WooShippingShipmentItem.fake()]],
1087+
shipments: [WooShippingShipment.fake()],
10881088
shippingLabelData: WooShippingLabelData(currentOrderLabels: [expectedShippingLabel])
10891089
)
10901090
remote.whenLoadingConfig(siteID: sampleSiteID, thenReturn: .success(expectedResponse))

WooCommerce/Classes/ViewModels/Order Details/OrderDetailsDataSource.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1696,7 +1696,6 @@ extension OrderDetailsDataSource {
16961696
}
16971697
}
16981698

1699-
17001699
// MARK: - Constants
17011700
extension OrderDetailsDataSource {
17021701
enum Localization {

0 commit comments

Comments
 (0)