Skip to content

Commit

Permalink
[Shipping labels] Add Networking support for getting list of packages (
Browse files Browse the repository at this point in the history
  • Loading branch information
bozidarsevo authored Nov 19, 2024
2 parents 09e8f0e + 7573842 commit beff276
Show file tree
Hide file tree
Showing 17 changed files with 584 additions and 19 deletions.
35 changes: 35 additions & 0 deletions Fakes/Fakes/Networking.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2761,6 +2761,18 @@ extension Networking.WooShippingCreatePackageResponse {
)
}
}
extension Networking.WooShippingPackagesResponse {
/// Returns a "ready to use" type filled with fake values.
///
public static func fake() -> Networking.WooShippingPackagesResponse {
.init(
storeOptions: .fake(),
customPackages: .fake(),
savedPredefinedPackages: .fake(),
allPredefinedOptions: .fake()
)
}
}
extension Networking.WooShippingCustomPackage {
/// Returns a "ready to use" type filled with fake values.
///
Expand All @@ -2778,12 +2790,35 @@ extension Networking.WooShippingPredefinedOption {
/// Returns a "ready to use" type filled with fake values.
///
public static func fake() -> Networking.WooShippingPredefinedOption {
.init(
title: .fake(),
providerID: .fake(),
predefinedPackages: .fake()
)
}
}
extension Networking.WooShippingPredefinedSavedOption {
/// Returns a "ready to use" type filled with fake values.
///
public static func fake() -> Networking.WooShippingPredefinedSavedOption {
.init(
id: .fake(),
predefinedPackageIDs: .fake()
)
}
}
extension Networking.WooShippingPredefinedPackage {
/// Returns a "ready to use" type filled with fake values.
///
public static func fake() -> Networking.WooShippingPredefinedPackage {
.init(id: .fake(),
name: .fake(),
isLetter: .fake(),
dimensions: .fake(),
boxWeight: .fake(),
groupId: .fake())
}
}
extension Networking.WordPressMedia {
/// Returns a "ready to use" type filled with fake values.
///
Expand Down
24 changes: 24 additions & 0 deletions Networking/Networking.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,12 @@
D8FBFF2422D52815006E3336 /* order-stats-v4-daily.json in Resources */ = {isa = PBXBuildFile; fileRef = D8FBFF2322D52815006E3336 /* order-stats-v4-daily.json */; };
D8FBFF2722D529F2006E3336 /* order-stats-v4-month.json in Resources */ = {isa = PBXBuildFile; fileRef = D8FBFF2622D529F2006E3336 /* order-stats-v4-month.json */; };
D8FBFF2922D52AFB006E3336 /* order-stats-v4-year.json in Resources */ = {isa = PBXBuildFile; fileRef = D8FBFF2822D52AFA006E3336 /* order-stats-v4-year.json */; };
DAA259AB2CEC86370035F028 /* WooShippingSavedPredefinedPackage.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA259AA2CEC86360035F028 /* WooShippingSavedPredefinedPackage.swift.swift */; };
DAA259AD2CEC86BE0035F028 /* wooshipping-get-packages-success.json in Resources */ = {isa = PBXBuildFile; fileRef = DAA259AC2CEC86BE0035F028 /* wooshipping-get-packages-success.json */; };
DAF367A22CE75B9E00D1B327 /* WooShippingPackagesMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF367A12CE75B9D00D1B327 /* WooShippingPackagesMapper.swift */; };
DAF367A42CE75C1B00D1B327 /* WooShippingPredefinedPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF367A32CE75C1900D1B327 /* WooShippingPredefinedPackage.swift */; };
DAF367A62CE75C2F00D1B327 /* WooShippingPredefinedSavedOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF367A52CE75C2D00D1B327 /* WooShippingPredefinedSavedOption.swift */; };
DAF367A82CE75C5C00D1B327 /* WooShippingPackagesResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF367A72CE75C5B00D1B327 /* WooShippingPackagesResponse.swift */; };
DE02ABB12B5636FC008E0AC4 /* BlazePaymentInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE02ABB02B5636FC008E0AC4 /* BlazePaymentInfo.swift */; };
DE02ABB32B563E61008E0AC4 /* blaze-payment-info.json in Resources */ = {isa = PBXBuildFile; fileRef = DE02ABB22B563E61008E0AC4 /* blaze-payment-info.json */; };
DE02ABB52B563E96008E0AC4 /* BlazePaymentInfoMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE02ABB42B563E96008E0AC4 /* BlazePaymentInfoMapper.swift */; };
Expand Down Expand Up @@ -2119,6 +2125,12 @@
D8FBFF2322D52815006E3336 /* order-stats-v4-daily.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "order-stats-v4-daily.json"; sourceTree = "<group>"; };
D8FBFF2622D529F2006E3336 /* order-stats-v4-month.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "order-stats-v4-month.json"; sourceTree = "<group>"; };
D8FBFF2822D52AFA006E3336 /* order-stats-v4-year.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "order-stats-v4-year.json"; sourceTree = "<group>"; };
DAA259AA2CEC86360035F028 /* WooShippingSavedPredefinedPackage.swift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSavedPredefinedPackage.swift.swift; sourceTree = "<group>"; };
DAA259AC2CEC86BE0035F028 /* wooshipping-get-packages-success.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "wooshipping-get-packages-success.json"; sourceTree = "<group>"; };
DAF367A12CE75B9D00D1B327 /* WooShippingPackagesMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingPackagesMapper.swift; sourceTree = "<group>"; };
DAF367A32CE75C1900D1B327 /* WooShippingPredefinedPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingPredefinedPackage.swift; sourceTree = "<group>"; };
DAF367A52CE75C2D00D1B327 /* WooShippingPredefinedSavedOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingPredefinedSavedOption.swift; sourceTree = "<group>"; };
DAF367A72CE75C5B00D1B327 /* WooShippingPackagesResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingPackagesResponse.swift; sourceTree = "<group>"; };
DE02ABB02B5636FC008E0AC4 /* BlazePaymentInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlazePaymentInfo.swift; sourceTree = "<group>"; };
DE02ABB22B563E61008E0AC4 /* blaze-payment-info.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "blaze-payment-info.json"; sourceTree = "<group>"; };
DE02ABB42B563E96008E0AC4 /* BlazePaymentInfoMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlazePaymentInfoMapper.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2537,6 +2549,7 @@
isa = PBXGroup;
children = (
CEC7D5902CDD0C1C00111B79 /* WooShippingCreatePackageResponse.swift */,
DAF367A72CE75C5B00D1B327 /* WooShippingPackagesResponse.swift */,
451A97C82609FF050059D135 /* ShippingLabelPackagesResponse.swift */,
451A97CC260A01A40059D135 /* ShippingLabelStoreOptions.swift */,
CCAAD10E2683974000909664 /* ShippingLabelPackagePurchase.swift */,
Expand All @@ -2561,6 +2574,9 @@
isa = PBXGroup;
children = (
CEC7D5922CDD0D9900111B79 /* WooShippingPredefinedOption.swift */,
DAF367A32CE75C1900D1B327 /* WooShippingPredefinedPackage.swift */,
DAA259AA2CEC86360035F028 /* WooShippingSavedPredefinedPackage.swift.swift */,
DAF367A52CE75C2D00D1B327 /* WooShippingPredefinedSavedOption.swift */,
451A97E8260B657D0059D135 /* ShippingLabelPredefinedOption.swift */,
451A97E4260B631E0059D135 /* ShippingLabelPredefinedPackage.swift */,
);
Expand Down Expand Up @@ -3497,6 +3513,7 @@
95122E3D2CB82C0A0079FF0A /* generate-product-success-wrapped.json */,
CE0F4EC82CE3753F006339BD /* wooshipping-get-label-rates-success.json */,
CE0F4ECC2CE375DD006339BD /* wooshipping-get-label-rates-error.json */,
DAA259AC2CEC86BE0035F028 /* wooshipping-get-packages-success.json */,
);
path = Responses;
sourceTree = "<group>";
Expand Down Expand Up @@ -3605,6 +3622,7 @@
CC0786C4267BAF0F00BA9AC1 /* ShippingLabelStatusMapper.swift */,
CEC7D5942CDD164D00111B79 /* WooShippingCreatePackageMapper.swift */,
CE0F4ECE2CE37C4F006339BD /* WooShippingLabelRatesMapper.swift */,
DAF367A12CE75B9D00D1B327 /* WooShippingPackagesMapper.swift */,
CE606D8E2BE39426001CB424 /* ShippingMethodMapper.swift */,
FE28F6E326842848004465C7 /* UserMapper.swift */,
077F39D326A58DE700ABEADC /* SystemStatusMapper.swift */,
Expand Down Expand Up @@ -4492,6 +4510,7 @@
02EFF81D2ABC3D0E0015ABB2 /* order-gift-card-invalid-error.json in Resources */,
02C54CC624D3E938007D658F /* product-variations-load-all-manage-stock-two-states.json in Resources */,
D823D90722376B4800C90817 /* shipment_tracking_new_custom_provider.json in Resources */,
DAA259AD2CEC86BE0035F028 /* wooshipping-get-packages-success.json in Resources */,
74A1D264211898F000931DFA /* site-visits-week.json in Resources */,
EE57C127297F8E5E00BC31E7 /* product-attribute-terms-without-data.json in Resources */,
CCEC5E9129E9BF1400912D6B /* product-variation-subscription.json in Resources */,
Expand Down Expand Up @@ -4947,6 +4966,7 @@
453305E92459DF2100264E50 /* PostMapper.swift in Sources */,
E12552C526385B05001CEE70 /* ShippingLabelAddressValidationSuccess.swift in Sources */,
456F71D424CB1E2400472EC1 /* ProductTagFromBatchCreation.swift in Sources */,
DAF367A42CE75C1B00D1B327 /* WooShippingPredefinedPackage.swift in Sources */,
CEB9BF412BB198860007978A /* ProductBundleStatsRemote.swift in Sources */,
2685C0FA263B5D5300D9EE97 /* AddOnGroupMapper.swift in Sources */,
CCE5F38D29EFFBC400087332 /* SubscriptionListMapper.swift in Sources */,
Expand Down Expand Up @@ -5091,6 +5111,7 @@
B554FA912180BCFC00C54DFF /* NoteHash.swift in Sources */,
68F48B0D28E3B2E80045C15B /* WCAnalyticsCustomerMapper.swift in Sources */,
CE0A0F19223987DF0075ED8D /* ProductListMapper.swift in Sources */,
DAA259AB2CEC86370035F028 /* WooShippingSavedPredefinedPackage.swift.swift in Sources */,
DEB3877E2C2A9DE20025256E /* GoogleListingsAndAdsRemote.swift in Sources */,
26BD9FCF2965EE71004E0D15 /* ProductVariationsBulkCreateMapper.swift in Sources */,
DE4D23BC29B5FC0D003A4B5D /* AnnouncementListMapper.swift in Sources */,
Expand Down Expand Up @@ -5125,6 +5146,7 @@
DE20046C2BFB4D4600660A72 /* ProductReport.swift in Sources */,
4599FC5E24A62AA70056157A /* ProductTagsRemote.swift in Sources */,
DEC51AE7276848A9009F3DF4 /* SystemStatus+Environment.swift in Sources */,
DAF367A82CE75C5C00D1B327 /* WooShippingPackagesResponse.swift in Sources */,
DE02ABB12B5636FC008E0AC4 /* BlazePaymentInfo.swift in Sources */,
FE28F6E226840DED004465C7 /* User.swift in Sources */,
7426CA0F21AF2C90004E9FFC /* SiteAPI.swift in Sources */,
Expand Down Expand Up @@ -5169,6 +5191,7 @@
EE1D9A9F2ACD6BA60020D817 /* AIProduct.swift in Sources */,
CE583A0E2109154500D73C1C /* OrderNoteMapper.swift in Sources */,
D8FBFF0D22D3AF4A006E3336 /* StatsGranularityV4.swift in Sources */,
DAF367A22CE75B9E00D1B327 /* WooShippingPackagesMapper.swift in Sources */,
261870782540A252006522A1 /* ShippingLineTax.swift in Sources */,
DEB3878C2C2D70EF0025256E /* GoogleAdsCampaignListMapper.swift in Sources */,
CE0F4ECF2CE37C4F006339BD /* WooShippingLabelRatesMapper.swift in Sources */,
Expand Down Expand Up @@ -5322,6 +5345,7 @@
DE2E8EB329546501002E4B14 /* PlaceholderDataValidator.swift in Sources */,
2665032E261F4FBF0079A159 /* ProductAddOnOption.swift in Sources */,
E18152C028F85D4A0011A0EC /* InAppPurchasesProductMapper.swift in Sources */,
DAF367A62CE75C2F00D1B327 /* WooShippingPredefinedSavedOption.swift in Sources */,
EE8A30302B72A3C8001D7C66 /* OrderAttributionInfo.swift in Sources */,
028296F7237D588700E84012 /* ProductVariation.swift in Sources */,
DE4D23BA29B5FB3E003A4B5D /* AnnouncementsRemote.swift in Sources */,
Expand Down
26 changes: 26 additions & 0 deletions Networking/Networking/Mapper/WooShippingPackagesMapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

struct WooShippingPackagesMapper: Mapper {
/// (Attempts) to convert a dictionary into WooShippingPackagesResponse.
///
func map(response: Data) throws -> WooShippingPackagesResponse {
let decoder = JSONDecoder()
if hasDataEnvelope(in: response) {
return try decoder.decode(WooShippingPackagesMapperEnvelope.self, from: response).data
} else {
return try decoder.decode(WooShippingPackagesResponse.self, from: response)
}
}
}

/// WooShippingPackagesMapperEnvelope Disposable Entity:
/// `Woo Shipping Packages` endpoint returns the shipping label packages in the `data` key.
/// This entity allows us to do parse all the things with JSONDecoder.
///
private struct WooShippingPackagesMapperEnvelope: Decodable {
let data: WooShippingPackagesResponse

private enum CodingKeys: String, CodingKey {
case data = "data"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4045,7 +4045,7 @@ extension Networking.WooPaymentsPayoutsSchedule {
extension Networking.WooShippingCreatePackageResponse {
public func copy(
customPackages: CopiableProp<[WooShippingCustomPackage]> = .copy,
predefinedOptions: CopiableProp<[WooShippingPredefinedOption]> = .copy
predefinedOptions: CopiableProp<[WooShippingPredefinedSavedOption]> = .copy
) -> Networking.WooShippingCreatePackageResponse {
let customPackages = customPackages ?? self.customPackages
let predefinedOptions = predefinedOptions ?? self.predefinedOptions
Expand All @@ -4057,6 +4057,27 @@ extension Networking.WooShippingCreatePackageResponse {
}
}

extension Networking.WooShippingPackagesResponse {
public func copy(
storeOptions: CopiableProp<ShippingLabelStoreOptions> = .copy,
customPackages: CopiableProp<[WooShippingCustomPackage]> = .copy,
savedPredefinedPackages: CopiableProp<[WooShippingSavedPredefinedPackage]> = .copy,
allPredefinedOptions: CopiableProp<[WooShippingPredefinedOption]> = .copy
) -> Networking.WooShippingPackagesResponse {
let storeOptions = storeOptions ?? self.storeOptions
let customPackages = customPackages ?? self.customPackages
let savedPredefinedPackages = savedPredefinedPackages ?? self.savedPredefinedPackages
let allPredefinedOptions = allPredefinedOptions ?? self.allPredefinedOptions

return Networking.WooShippingPackagesResponse(
storeOptions: storeOptions,
customPackages: customPackages,
savedPredefinedPackages: savedPredefinedPackages,
allPredefinedOptions: allPredefinedOptions
)
}
}

extension Networking.WooShippingCustomPackage {
public func copy(
id: CopiableProp<String> = .copy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@ extension WooShippingCustomPackage: Codable {
let name = try container.decode(String.self, forKey: .name)
let type = try container.decode(String.self, forKey: .type)
let dimensions = try container.decode(String.self, forKey: .dimensions)
let boxWeight = try container.decode(Double.self, forKey: .boxWeight)

var boxWeight: Double = 0.0
// Looks like some endpoints have boxWeight as String and some as Double
if let boxWeightDouble = try? container.decodeIfPresent(Double.self, forKey: .boxWeight) {
boxWeight = boxWeightDouble
}
else if let boxWeightString = try? container.decodeIfPresent(String.self, forKey: .boxWeight),
let boxWeightDouble = Double(boxWeightString) {
boxWeight = boxWeightDouble
}

self.init(id: id, name: name, rawType: type, dimensions: dimensions, boxWeight: boxWeight)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,37 @@ import Codegen
///
public struct WooShippingPredefinedOption: Equatable, GeneratedFakeable {

/// The ID of the shipping carrier for the predefined option, e.g. "usps".
public let id: String
/// The title of the predefined option. It works like an ID, and it is unique.
public let title: String

/// List of saved predefined package IDs.
public let predefinedPackageIDs: [String]
/// The ID of the predefined option (shipping provider), e.g. "usps". This is required for activating predefined packages remotely.
public let providerID: String

public init(id: String, predefinedPackageIDs: [String]) {
self.id = id
self.predefinedPackageIDs = predefinedPackageIDs
/// List of predefined packages
public let predefinedPackages: [WooShippingPredefinedPackage]

public init(title: String, providerID: String, predefinedPackages: [WooShippingPredefinedPackage]) {
self.title = title
self.providerID = providerID
self.predefinedPackages = predefinedPackages
}
}

// MARK: Decodable
extension WooShippingPredefinedOption: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let title = try container.decode(String.self, forKey: .title)
let predefinedPackages = try container.decodeIfPresent([WooShippingPredefinedPackage].self, forKey: .predefinedPackages) ?? []
let providerID = try container.decodeIfPresent(String.self, forKey: .providerID) ?? ""

self.init(title: title, providerID: providerID, predefinedPackages: predefinedPackages)
}

private enum CodingKeys: String, CodingKey {
case title
case predefinedPackages
case providerID
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import Foundation
import Codegen
import WooFoundation

/// Represents a predefined Shipping Label Packages for the WooCommerce Shipping extension.
///
public struct WooShippingPredefinedPackage: Equatable, GeneratedFakeable, Identifiable {

/// The id of the predefined package
public let id: String

/// The name of the package, like `USPS Priority Mail Boxes`
public let name: String

/// Defines if package is a box or a letter. By default is a box, so it's equal to `false`
public let isLetter: Bool

/// Will be a string formatted like this: `21.91 x 13.65 x 4.13`
public let dimensions: String

public let boxWeight: String

// Will be a string for the groupId, like `pri_flat_boxes`
public let groupId: String

public init(id: String,
name: String,
isLetter: Bool,
dimensions: String,
boxWeight: String,
groupId: String) {
self.id = id
self.name = name
self.isLetter = isLetter
self.dimensions = dimensions
self.boxWeight = boxWeight
self.groupId = groupId
}

public func getLength() -> Double {
let firstComponent = dimensions.components(separatedBy: " x ").first ?? ""
return Double(firstComponent) ?? 0
}

public func getWidth() -> Double {
let secondComponent = dimensions.components(separatedBy: " x ")[safe: 1] ?? ""
return Double(secondComponent) ?? 0
}

public func getHeight() -> Double {
let lastComponent = dimensions.components(separatedBy: " x ").last ?? ""
return Double(lastComponent) ?? 0
}
}

// MARK: Decodable

extension WooShippingPredefinedPackage: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let id = try container.decode(String.self, forKey: .id)
let name = try container.decode(String.self, forKey: .name)
let isLetter = try container.decodeIfPresent(Bool.self, forKey: .isLetter) ?? false
let dimensions = try container.decode(String.self, forKey: .dimensions)
let groupId = try container.decode(String.self, forKey: .groupId)
var boxWeight: String = ""
// Looks like some endpoints have boxWeight as String and some as Double
if let boxWeightDouble = try? container.decodeIfPresent(Double.self, forKey: .boxWeight) {
boxWeight = String(boxWeightDouble)
}
else if let boxWeightString = try? container.decodeIfPresent(String.self, forKey: .boxWeight) {
boxWeight = boxWeightString
}

self.init(id: id,
name: name,
isLetter: isLetter,
dimensions: dimensions,
boxWeight: boxWeight,
groupId: groupId)
}

private enum CodingKeys: String, CodingKey {
case id
case name
case isLetter = "is_letter"
case dimensions
case groupId = "group_id"
case boxWeight = "box_weight"
}
}
Loading

0 comments on commit beff276

Please sign in to comment.