From 53431b7cc912f731dc798f91eeb1a9dc526d7b23 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 17:25:50 +0700 Subject: [PATCH 1/7] Add shipments to WooShippingCreateLabelsViewModel and inject it to the split view detail screen --- .../WooShippingSplitShipmentsDetailView.swift | 18 --- .../WooShippingSplitShipmentsRow.swift | 19 ---- .../WooShippingSplitShipmentsViewModel.swift | 63 +---------- .../WooShippingCreateLabelsView.swift | 4 +- .../WooShippingCreateLabelsViewModel.swift | 104 +++++++++++++++--- 5 files changed, 93 insertions(+), 115 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift index 1d8fcff46b5..def316c97c2 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift @@ -448,21 +448,3 @@ fileprivate extension WooShippingSplitShipmentsDetailView { } } } - -#if DEBUG -#Preview { - WooShippingSplitShipmentsDetailView(viewModel: WooShippingSplitShipmentsViewModel(order: ShippingLabelSampleData.sampleOrder(), - config: ShippingLabelSampleData.sampleWooShippingConfig(), - items: [ShippingLabelPackageItem(productOrVariationID: 1, - orderItemID: 12, - name: "Shirt", - weight: 0.5, - quantity: 2, - value: 9.99, - dimensions: ProductDimensions(length: "", - width: "", - height: ""), - attributes: [], - imageURL: nil)])) -} -#endif diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift index 5fb2f0232ca..de962bfa0f2 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift @@ -42,22 +42,3 @@ private extension WooShippingSplitShipmentsRow { comment: "Title for button in shipping label creation to start split shipments flow.") } } - -#if DEBUG -#Preview { - WooShippingSplitShipmentsRow(viewModel: WooShippingSplitShipmentsViewModel(order: ShippingLabelSampleData.sampleOrder(), - config: ShippingLabelSampleData.sampleWooShippingConfig(), - items: [ShippingLabelPackageItem(productOrVariationID: 1, - orderItemID: 12, - name: "Shirt", - weight: 0.5, - quantity: 2, - value: 9.99, - dimensions: ProductDimensions(length: "", - width: "", - height: ""), - attributes: [], - imageURL: nil)])) - .padding() -} -#endif diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift index f1d700098a8..98c73299b58 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift @@ -6,7 +6,6 @@ import WooFoundation final class WooShippingSplitShipmentsViewModel: ObservableObject { private let order: Order private let stores: StoresManager - private let config: WooShippingConfig private let currencySettings: CurrencySettings private let shippingSettingsService: ShippingSettingsService @@ -101,22 +100,15 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { @Published private(set) var isSavingShipmentInfo = false init(order: Order, - config: WooShippingConfig, - items: [ShippingLabelPackageItem], + shipments: [Shipment], stores: StoresManager = ServiceLocator.stores, currencySettings: CurrencySettings = ServiceLocator.currencySettings, shippingSettingsService: ShippingSettingsService = ServiceLocator.shippingSettingsService) { self.order = order - self.config = config self.stores = stores self.currencySettings = currencySettings self.shippingSettingsService = shippingSettingsService - - self.shipments = Self.createShipments(with: config, - packageItems: items, - currency: order.currency, - currencySettings: currencySettings, - shippingSettingsService: shippingSettingsService) + self.shipments = shipments shipmentsSavedInRemote = editedShipmentsInfo @@ -405,57 +397,6 @@ private extension WooShippingSplitShipmentsViewModel { extension WooShippingSplitShipmentsViewModel { - private static func createShipments(with config: WooShippingConfig, - packageItems: [ShippingLabelPackageItem], - currency: String, - currencySettings: CurrencySettings, - shippingSettingsService: ShippingSettingsService) -> [Shipment] { - guard config.shipments.isEmpty == false else { - let contents = packageItems.map { item in - CollapsibleShipmentItemCardViewModel(item: item, currency: currency) - } - let shipment = Shipment(contents: contents, - currency: currency, - currencySettings: currencySettings, - shippingSettingsService: shippingSettingsService) - return [shipment] - } - - let currentOrderLabels = config.shippingLabelData?.currentOrderLabels ?? [] - var shipments = [Shipment]() - - for key in config.shipments.keys.sorted() { - guard let shipmentItems = config.shipments[key] else { - continue - } - - let isPurchased = (currentOrderLabels.filter { $0.shipmentID == key}).isNotEmpty - - var shipmentContents = ShipmentContents() - for shipmentItem in shipmentItems { - guard let packageItem = packageItems.first(where: { $0.orderItemID == shipmentItem.id }), - let subItems = shipmentItem.subItems else { - continue - } - - let quantity = subItems.count > 0 ? subItems.count : 1 - let updatedItem = ShippingLabelPackageItem(copy: packageItem, quantity: Decimal(quantity)) - let content = CollapsibleShipmentItemCardViewModel(item: updatedItem, - isSelectable: !isPurchased, - currency: currency) - shipmentContents.append(content) - } - - let shipment = Shipment(contents: shipmentContents, - isPurchased: isPurchased, - currency: currency, - currencySettings: currencySettings, - shippingSettingsService: shippingSettingsService) - shipments.append(shipment) - } - return shipments - } - private func createShipment(with contents: [CollapsibleShipmentItemCardViewModel]) -> Shipment { Shipment(contents: contents, currency: order.currency, 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 ce5858ec721..db44e8f581b 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 @@ -105,8 +105,8 @@ private extension WooShippingCreateLabelsView { WooShippingPostPurchaseView(viewModel: postPurchase) } - if !viewModel.canViewLabel, let splitShipmentsViewModel = viewModel.splitShipmentsViewModel { - WooShippingSplitShipmentsRow(viewModel: splitShipmentsViewModel) + if !viewModel.canViewLabel { + WooShippingSplitShipmentsRow(viewModel: viewModel.splitShipmentsViewModel) } WooShippingItems(viewModel: viewModel.items) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift index f8d37e52076..027f55195b6 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift @@ -14,6 +14,7 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { } private let shippingSettingsService: ShippingSettingsService + private let currencySettings: CurrencySettings private let currencyFormatter: CurrencyFormatter private let itemsDataSource: WooShippingItemsDataSource private var destinationEmail: String? @@ -49,11 +50,13 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { /// View model for the items to ship. @Published private(set) var items: WooShippingItemsViewModel - /// ID for the shipment. - /// /// For now we support purchasing labels in a single shipment only, so we only need a single shipment ID. let shipmentID = "shipment_0" + typealias Shipment = WooShippingSplitShipmentsViewModel.Shipment + + @Published private(set) var shipments: [Shipment] + /// Selected package data for the shipping label. @Published private(set) var selectedPackage: WooShippingPackageDataRepresentable? @@ -64,7 +67,11 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { private(set) var shippingService: WooShippingServiceViewModel? /// View model for split shipments. - private(set) var splitShipmentsViewModel: WooShippingSplitShipmentsViewModel? + var splitShipmentsViewModel: WooShippingSplitShipmentsViewModel { + return WooShippingSplitShipmentsViewModel(order: order, + shipments: shipments, + stores: stores) + } /// Selected shipping rate when creating a shipping label. @Published private var selectedRate: WooShippingSelectedRate? @@ -211,6 +218,8 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { let itemsDataSource = itemsDataSource ?? DefaultWooShippingItemsDataSource(order: order) self.itemsDataSource = itemsDataSource self.items = WooShippingItemsViewModel(dataSource: itemsDataSource) + + self.currencySettings = currencySettings self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings) self.onLabelPurchase = onLabelPurchase self.destinationAddress = Self.getDestinationAddress(order: order, address: order.shippingAddress) @@ -223,6 +232,11 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { self.debounceDuration = debounceDuration self.shippingSettingsService = shippingSettingsService + self.shipments = Self.createShipments(packageItems: itemsDataSource.items, + currency: order.currency, + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) + loadDestinationAddress() observeSelectedOriginAddress() observeDestinationAddress() @@ -243,6 +257,7 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { stores: StoresManager = ServiceLocator.stores) { self.order = order self.shippingLabel = shippingLabel + self.currencySettings = currencySettings self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings) self.shippingSettingsService = shippingSettingsService self.postPurchase = WooShippingPostPurchaseViewModel(shippingLabel: shippingLabel) @@ -254,6 +269,12 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { self.destinationAddressStatus = .verified self.onLabelPurchase = nil self.stores = stores + + self.shipments = Self.createShipments(packageItems: itemsDataSource.items, + currency: order.currency, + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) + Task { await loadRequiredData() } @@ -275,12 +296,8 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { } } - let totalOrderItems = order.items.map(\.quantity).reduce(0, +) - if totalOrderItems > 1 { - // Only fetch shipments info if there are more than one order items. - group.addTask { - await self.loadShipmentsInfo() - } + group.addTask { + await self.loadShipmentsInfo() } } @@ -447,12 +464,12 @@ private extension WooShippingCreateLabelsViewModel { stores.dispatch(action) } - if let config { - splitShipmentsViewModel = WooShippingSplitShipmentsViewModel(order: order, - config: config, - items: items.dataSource.items, - stores: stores) - } + guard let config else { return } + shipments = Self.createShipments(with: config, + packageItems: itemsDataSource.items, + currency: order.currency, + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) } /// Loads destination address of the order from remote. @@ -657,6 +674,57 @@ private extension WooShippingCreateLabelsViewModel { hazmatCategory: hazmatCategory?.rawValue, customsForm: customsForm) } + + static func createShipments(with config: WooShippingConfig? = nil, + packageItems: [ShippingLabelPackageItem], + currency: String, + currencySettings: CurrencySettings, + shippingSettingsService: ShippingSettingsService) -> [Shipment] { + guard let config, config.shipments.isEmpty == false else { + let contents = packageItems.map { item in + CollapsibleShipmentItemCardViewModel(item: item, currency: currency) + } + let shipment = Shipment(contents: contents, + currency: currency, + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) + return [shipment] + } + + let currentOrderLabels = config.shippingLabelData?.currentOrderLabels ?? [] + var shipments = [Shipment]() + + for key in config.shipments.keys.sorted() { + guard let shipmentItems = config.shipments[key] else { + continue + } + + let isPurchased = (currentOrderLabels.filter { $0.shipmentID == key}).isNotEmpty + + var shipmentContents = [CollapsibleShipmentItemCardViewModel]() + for shipmentItem in shipmentItems { + guard let packageItem = packageItems.first(where: { $0.orderItemID == shipmentItem.id }), + let subItems = shipmentItem.subItems else { + continue + } + + let quantity = subItems.count > 0 ? subItems.count : 1 + let updatedItem = ShippingLabelPackageItem(copy: packageItem, quantity: Decimal(quantity)) + let content = CollapsibleShipmentItemCardViewModel(item: updatedItem, + isSelectable: !isPurchased, + currency: currency) + shipmentContents.append(content) + } + + let shipment = Shipment(contents: shipmentContents, + isPurchased: isPurchased, + currency: currency, + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) + shipments.append(shipment) + } + return shipments + } } private extension WooShippingCreateLabelsViewModel { @@ -736,6 +804,12 @@ private extension WooShippingCreateLabelsViewModel { value: "Undo", comment: "Button to undo a change on the shipping label creation screen" ) + + static let shipmentFormat = NSLocalizedString( + "wooShipping.createLabels.shipmentFormat", + value: "Shipment %1$d", + comment: "Label for a shipment during shipping label creation. The placeholder is the index of the shipment. Reads like: 'Shipment 1'" + ) } } From 651ce1799692d93d3c3c9bcd1ddae7e42151e673 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 18:33:47 +0700 Subject: [PATCH 2/7] Update initializer for Shipment --- .../WooShippingSplitShipmentsDetailView.swift | 2 +- .../WooShippingSplitShipmentsViewModel.swift | 75 +++++++++---------- .../WooShippingCreateLabelsViewModel.swift | 12 +-- 3 files changed, 38 insertions(+), 51 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift index def316c97c2..ec5eec45776 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift @@ -38,7 +38,7 @@ struct WooShippingSplitShipmentsDetailView: View { } VStack(spacing: Layout.verticalSpacing) { - ForEach(viewModel.currentShipment.contents) { item in + ForEach(viewModel.currentShipment.splitShipmentViewModels) { item in CollapsibleShipmentItemCard(viewModel: item) } } diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift index 98c73299b58..0fa290f78cd 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsViewModel.swift @@ -9,7 +9,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { private let currencySettings: CurrencySettings private let shippingSettingsService: ShippingSettingsService - typealias ShipmentContents = [CollapsibleShipmentItemCardViewModel] + typealias ShipmentContents = [ShippingLabelPackageItem] @Published private(set) var shipments: [Shipment] @@ -36,7 +36,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { shipmentIdsToUpdate.append(key) var items = [WooShippingShipmentItem]() - for item in shipment.contents { + for item in shipment.splitShipmentViewModels { if let mainItemID = Int(item.mainItemRow.itemID) { let i = WooShippingShipmentItem(id: Int64(mainItemID), subItems: item.childItemRows.map({ $0.itemID })) @@ -122,7 +122,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { } func selectAll() { - currentShipment.contents.forEach { + currentShipment.splitShipmentViewModels.forEach { $0.selectAll() } } @@ -148,27 +148,19 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { // Step 1: Split items var newShipmentContents = ShipmentContents() var movedItems = ShipmentContents() - for item in currentShipment.contents { + for item in currentShipment.splitShipmentViewModels { let initialQuantity = item.packageItem.quantity.intValue let selectedQuantity = item.numberOfSelectedItems let remainingQuantity = initialQuantity - selectedQuantity if remainingQuantity == 0 { - movedItems.append( - CollapsibleShipmentItemCardViewModel(item: item.packageItem, currency: order.currency) - ) + movedItems.append(item.packageItem) } else if selectedQuantity > 0 { let newItem = ShippingLabelPackageItem(copy: item.packageItem, quantity: Decimal(remainingQuantity)) - newShipmentContents.append( - CollapsibleShipmentItemCardViewModel(item: newItem, currency: order.currency) - ) + newShipmentContents.append(newItem) let movedItem = ShippingLabelPackageItem(copy: item.packageItem, quantity: Decimal(selectedQuantity)) - movedItems.append( - CollapsibleShipmentItemCardViewModel(item: movedItem, currency: order.currency) - ) + movedItems.append(movedItem) } else if selectedQuantity == 0 { - newShipmentContents.append( - CollapsibleShipmentItemCardViewModel(item: item.packageItem, currency: order.currency) - ) + newShipmentContents.append(item.packageItem) } } @@ -177,7 +169,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { // Step 3: Add new or update existing shipment let totalItemsMoved = movedItems - .map { $0.packageItem.quantity } + .map { $0.quantity } .reduce(0, +) var updatedShipmentIndex: Int? @@ -191,15 +183,13 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { var updatedShipmentContents = ShipmentContents() for item in shipments[index].contents { let matchingItemIndex = movedItems.firstIndex(where: { - $0.packageItem.productOrVariationID == item.packageItem.productOrVariationID + $0.productOrVariationID == item.productOrVariationID }) if let matchingItemIndex { // Merge the quantity if the same item is moved to the shipment - let updatedQuantity = item.packageItem.quantity + movedItems[matchingItemIndex].packageItem.quantity - let updatedItem = ShippingLabelPackageItem(copy: item.packageItem, quantity: updatedQuantity) - updatedShipmentContents.append( - CollapsibleShipmentItemCardViewModel(item: updatedItem, currency: order.currency) - ) + let updatedQuantity = item.quantity + movedItems[matchingItemIndex].quantity + let updatedItem = ShippingLabelPackageItem(copy: item, quantity: updatedQuantity) + updatedShipmentContents.append(updatedItem) movedItems.remove(at: matchingItemIndex) } else { // Keep the item as-is @@ -265,13 +255,13 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { unfulfilledShipments.forEach { shipment in for item in shipment.contents { let matchingItemIndex = mergedShipmentContents.firstIndex(where: { - $0.packageItem.productOrVariationID == item.packageItem.productOrVariationID + $0.productOrVariationID == item.productOrVariationID }) if let matchingItemIndex { // Merge the quantity if the same item is merged to the shipment - let updatedQuantity = item.packageItem.quantity + mergedShipmentContents[matchingItemIndex].packageItem.quantity - let updatedItem = ShippingLabelPackageItem(copy: item.packageItem, quantity: updatedQuantity) - mergedShipmentContents[matchingItemIndex] = CollapsibleShipmentItemCardViewModel(item: updatedItem, currency: order.currency) + let updatedQuantity = item.quantity + mergedShipmentContents[matchingItemIndex].quantity + let updatedItem = ShippingLabelPackageItem(copy: item, quantity: updatedQuantity) + mergedShipmentContents[matchingItemIndex] = updatedItem } else { // Keep the item as-is mergedShipmentContents.append(item) @@ -307,13 +297,13 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { for item in shipment.contents { let matchingItemIndex = mergedContents.firstIndex(where: { - $0.packageItem.productOrVariationID == item.packageItem.productOrVariationID + $0.productOrVariationID == item.productOrVariationID }) if let matchingItemIndex { // Merge the quantity if the same item is merged to the shipment - let updatedQuantity = item.packageItem.quantity + mergedContents[matchingItemIndex].packageItem.quantity - let updatedItem = ShippingLabelPackageItem(copy: item.packageItem, quantity: updatedQuantity) - mergedContents[matchingItemIndex] = CollapsibleShipmentItemCardViewModel(item: updatedItem, currency: order.currency) + let updatedQuantity = item.quantity + mergedContents[matchingItemIndex].quantity + let updatedItem = ShippingLabelPackageItem(copy: item, quantity: updatedQuantity) + mergedContents[matchingItemIndex] = updatedItem } else { // Append the item as-is mergedContents.append(item) @@ -329,7 +319,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject { private extension WooShippingSplitShipmentsViewModel { func configureSelectionCallback() { - currentShipment.contents.forEach { viewModel in + currentShipment.splitShipmentViewModels.forEach { viewModel in viewModel.onSelectionChange = { [weak self] in self?.updateMoveToNotice() } @@ -361,7 +351,7 @@ private extension WooShippingSplitShipmentsViewModel { func updateMoveToNotice() { let currentIndex = selectedShipmentIndex - let selectedItemsCount = currentShipment.contents + let selectedItemsCount = currentShipment.splitShipmentViewModels .map(\.numberOfSelectedItems) .reduce(0, +) @@ -370,7 +360,7 @@ private extension WooShippingSplitShipmentsViewModel { } let totalItemCount = currentShipment.contents - .map { $0.packageItem.quantity } + .map { $0.quantity } .reduce(0, +).intValue if shipments.count == 1 && @@ -397,7 +387,7 @@ private extension WooShippingSplitShipmentsViewModel { extension WooShippingSplitShipmentsViewModel { - private func createShipment(with contents: [CollapsibleShipmentItemCardViewModel]) -> Shipment { + private func createShipment(with contents: [ShippingLabelPackageItem]) -> Shipment { Shipment(contents: contents, currency: order.currency, currencySettings: currencySettings, @@ -407,7 +397,8 @@ extension WooShippingSplitShipmentsViewModel { struct Shipment: Identifiable, Equatable { let id = UUID().uuidString - let contents: [CollapsibleShipmentItemCardViewModel] + let contents: [ShippingLabelPackageItem] + let splitShipmentViewModels: [CollapsibleShipmentItemCardViewModel] let isPurchased: Bool let quantity: String @@ -420,19 +411,21 @@ extension WooShippingSplitShipmentsViewModel { "\(weight) • \(price)" } - init(contents: [CollapsibleShipmentItemCardViewModel], + init(contents: [ShippingLabelPackageItem], isPurchased: Bool = false, currency: String, currencySettings: CurrencySettings, shippingSettingsService: ShippingSettingsService) { self.contents = contents + self.splitShipmentViewModels = contents.map { + CollapsibleShipmentItemCardViewModel(item: $0, isSelectable: !isPurchased, currency: currency) + } self.isPurchased = isPurchased - let items = contents.map(\.packageItem) - let itemsCount = items.map(\.quantity).reduce(0, +) + let itemsCount = contents.map(\.quantity).reduce(0, +) self.quantity = Localization.itemsCount(itemsCount) - self.weight = formatWeight(for: items) - self.price = formatPrice(for: items) + self.weight = formatWeight(for: contents) + self.price = formatPrice(for: contents) /// Calculates and formats the total weight of the given items based on each item's weight and quantity. /// diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift index 027f55195b6..f82720e37cd 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift @@ -681,10 +681,7 @@ private extension WooShippingCreateLabelsViewModel { currencySettings: CurrencySettings, shippingSettingsService: ShippingSettingsService) -> [Shipment] { guard let config, config.shipments.isEmpty == false else { - let contents = packageItems.map { item in - CollapsibleShipmentItemCardViewModel(item: item, currency: currency) - } - let shipment = Shipment(contents: contents, + let shipment = Shipment(contents: packageItems, currency: currency, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -701,7 +698,7 @@ private extension WooShippingCreateLabelsViewModel { let isPurchased = (currentOrderLabels.filter { $0.shipmentID == key}).isNotEmpty - var shipmentContents = [CollapsibleShipmentItemCardViewModel]() + var shipmentContents = [ShippingLabelPackageItem]() for shipmentItem in shipmentItems { guard let packageItem = packageItems.first(where: { $0.orderItemID == shipmentItem.id }), let subItems = shipmentItem.subItems else { @@ -710,10 +707,7 @@ private extension WooShippingCreateLabelsViewModel { let quantity = subItems.count > 0 ? subItems.count : 1 let updatedItem = ShippingLabelPackageItem(copy: packageItem, quantity: Decimal(quantity)) - let content = CollapsibleShipmentItemCardViewModel(item: updatedItem, - isSelectable: !isPurchased, - currency: currency) - shipmentContents.append(content) + shipmentContents.append(updatedItem) } let shipment = Shipment(contents: shipmentContents, From 46e6858f68db6bfd3da2cfc1308d49200d122105 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 18:38:01 +0700 Subject: [PATCH 3/7] Restore check for loadShipmentsInfo --- .../WooShippingCreateLabelsViewModel.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift index f82720e37cd..871b27d0d1f 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift @@ -296,8 +296,12 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { } } - group.addTask { - await self.loadShipmentsInfo() + let totalOrderItems = order.items.map(\.quantity).reduce(0, +) + if totalOrderItems > 1 { + // Only fetch shipments info if there are more than one order items. + group.addTask { + await self.loadShipmentsInfo() + } } } From 339804fced9f8f549ba6582ff03810e09751bdca Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 18:57:20 +0700 Subject: [PATCH 4/7] Update tests for WooShippingSplitShipmentViewModel --- ...ShippingSplitShipmentsViewModelTests.swift | 340 +++++++----------- 1 file changed, 137 insertions(+), 203 deletions(-) diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/Split shipments/WooShippingSplitShipmentsViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/Split shipments/WooShippingSplitShipmentsViewModelTests.swift index 88b68e679dd..1eb9ee44c14 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/Split shipments/WooShippingSplitShipmentsViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/Split shipments/WooShippingSplitShipmentsViewModelTests.swift @@ -12,6 +12,8 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let sampleOrder = Order.fake().copy(currency: "INR") + typealias Shipment = WooShippingSplitShipmentsViewModel.Shipment + override func setUp() { currencySettings = CurrencySettings() shippingSettingsService = MockShippingSettingsService(dimensionUnit: "cm", @@ -25,8 +27,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // When let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -42,8 +43,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // When let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // Then @@ -57,8 +57,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // When let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // Then @@ -72,8 +71,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // When let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -81,54 +79,6 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { assertEqual("13 kg • ₹22.50", viewModel.itemsDetailLabel) } - func test_shipments_is_correct_initially_if_config_is_empty() throws { - // Given - let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), - sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] - - // When - let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, - currencySettings: currencySettings, - shippingSettingsService: shippingSettingsService) - - // Then - XCTAssertEqual(viewModel.shipments.count, 1) - let shipment = try XCTUnwrap(viewModel.shipments.first) - XCTAssertEqual(shipment.contents.count, items.count) - } - - func test_shipments_is_correct_initially_if_config_is_not_empty() throws { - // Given - let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), - sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] - - // When - let shippingLabelData = WooShippingLabelData(currentOrderLabels: [ShippingLabelPurchase.fake().copy(shipmentID: "2")]) - let config = WooShippingConfig(siteID: 123, shipments: [ - "1": [WooShippingShipmentItem(id: 1, subItems: ["sub-1", "sub-2"])], - "2": [WooShippingShipmentItem(id: 2, subItems: [])] - ], shippingLabelData: shippingLabelData) - let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: config, - items: items, - currencySettings: currencySettings, - shippingSettingsService: shippingSettingsService) - - // Then - XCTAssertEqual(viewModel.shipments.count, 2) - XCTAssertEqual(viewModel.shipments[0].contents.count, 1) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 2) - XCTAssertFalse(viewModel.shipments[0].isPurchased) - - XCTAssertEqual(viewModel.shipments[1].contents.count, 1) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 1) - XCTAssertTrue(viewModel.shipments[1].isPurchased) - } - // MARK: - `moveToNoticeViewModel` func test_moveToNoticeViewModel_is_nil_initially() { @@ -138,8 +88,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // When let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -153,8 +102,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -171,13 +119,12 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() // Then let moveToNoticeViewModel = try XCTUnwrap(viewModel.moveToNoticeViewModel) @@ -192,15 +139,14 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.last?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.mainItemRow.handleTap() // Then let moveToNoticeViewModel = try XCTUnwrap(viewModel.moveToNoticeViewModel) @@ -215,13 +161,12 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) viewModel.selectAll() @@ -239,27 +184,26 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 2) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 1) XCTAssertEqual(viewModel.shipments[1].contents.count, 1) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 1) } func test_moveSelectedItems_to_new_shipments_works_correctly_when_moving_whole_item() { @@ -267,25 +211,24 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 1) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 1) XCTAssertEqual(viewModel.shipments[1].contents.count, 1) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 2) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 2) } func test_moveSelectedItems_to_existing_shipments_works_correctly() { @@ -294,31 +237,30 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.last?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .existingShipment(index: 1)) // Then XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 2) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 1) XCTAssertEqual(viewModel.shipments[1].contents.count, 2) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[1].contents[1].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[1].packageItem.quantity, 3) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 1) + XCTAssertEqual(viewModel.shipments[1].contents[1].orderItemID, items[2].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[1].quantity, 3) } func test_moveSelectedItems_to_existing_shipments_merges_the_same_items() { @@ -327,31 +269,30 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.last?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.last?.childItemRows.last?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.childItemRows.last?.handleTap() viewModel.moveSelectedItems(to: .existingShipment(index: 1)) // Then XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 3) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 2) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[0].contents[2].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[2].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 2) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[2].orderItemID, items[2].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[2].quantity, 1) XCTAssertEqual(viewModel.shipments[1].contents.count, 1) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 2) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[2].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 2) } func test_moveSelectedItems_removes_empty_shipment_after_moving() { @@ -359,25 +300,24 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.last?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.first?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .existingShipment(index: 1)) // Then XCTAssertEqual(viewModel.shipments.count, 1) XCTAssertEqual(viewModel.shipments[0].contents.count, 2) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 2) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 2) } func test_moveSelectedItems_to_new_shipments_updates_section_headers_for_current_shipment() { @@ -385,13 +325,12 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then @@ -405,13 +344,12 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) viewModel.selectedShipmentIndex = 1 @@ -426,14 +364,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) XCTAssertEqual(viewModel.topTabItems.count, 1) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then @@ -445,14 +382,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) XCTAssertNil(viewModel.movingCompletionMessage) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then @@ -470,22 +406,21 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 2), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) - viewModel.shipments.first?.contents.first?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Confidence checks XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 1) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 1) XCTAssertEqual(viewModel.shipments[1].contents.count, 1) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 2) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 2) // When viewModel.undoMovingItems() @@ -494,10 +429,10 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { XCTAssertEqual(viewModel.shipments.count, 1) XCTAssertEqual(viewModel.shipments[0].contents.count, 2) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 2) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 2) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 1) } // MARK: - `saveShipmentInfo` @@ -509,14 +444,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 3), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], stores: stores, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // Moving items to 2 new shipments - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) var receivedShipmentToUpdate: WooShippingUpdateShipment? @@ -548,15 +482,14 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // Moving items to 2 new shipments - viewModel.shipments.first?.contents.last?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.last?.childItemRows.last?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.childItemRows.last?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Confidence checks @@ -568,15 +501,15 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // Then XCTAssertEqual(shipmentsToMerge.count, 2) XCTAssertEqual(shipmentsToMerge[0].contents.count, 3) - XCTAssertEqual(shipmentsToMerge[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(shipmentsToMerge[0].contents[0].packageItem.quantity, 2) - XCTAssertEqual(shipmentsToMerge[0].contents[1].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(shipmentsToMerge[0].contents[1].packageItem.quantity, 1) - XCTAssertEqual(shipmentsToMerge[0].contents[2].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(shipmentsToMerge[0].contents[2].packageItem.quantity, 1) + XCTAssertEqual(shipmentsToMerge[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(shipmentsToMerge[0].contents[0].quantity, 2) + XCTAssertEqual(shipmentsToMerge[0].contents[1].orderItemID, items[1].orderItemID) + XCTAssertEqual(shipmentsToMerge[0].contents[1].quantity, 1) + XCTAssertEqual(shipmentsToMerge[0].contents[2].orderItemID, items[2].orderItemID) + XCTAssertEqual(shipmentsToMerge[0].contents[2].quantity, 1) XCTAssertEqual(shipmentsToMerge[1].contents.count, 1) - XCTAssertEqual(shipmentsToMerge[1].contents[0].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(shipmentsToMerge[1].contents[0].packageItem.quantity, 1) + XCTAssertEqual(shipmentsToMerge[1].contents[0].orderItemID, items[2].orderItemID) + XCTAssertEqual(shipmentsToMerge[1].contents[0].quantity, 1) } // MARK: - `removeShipment` @@ -587,15 +520,14 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // Moving items to 2 new shipments - viewModel.shipments.first?.contents.last?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.last?.mainItemRow.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.mainItemRow.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Confidence checks @@ -607,13 +539,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // Then XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 1) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 2) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 2) XCTAssertEqual(viewModel.shipments[1].contents.count, 2) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[1].contents[1].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[1].packageItem.quantity, 3) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 1) + XCTAssertEqual(viewModel.shipments[1].contents[1].orderItemID, items[2].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[1].quantity, 3) } // MARK: - `mergeAllUnfulfilledShipments` @@ -624,15 +556,14 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, - currencySettings: currencySettings, - shippingSettingsService: shippingSettingsService) + shipments: [createShipment(with: items)], + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) // Moving items to 2 new shipments - viewModel.shipments.first?.contents.last?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) - viewModel.shipments.first?.contents.last?.childItemRows.last?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.last?.childItemRows.last?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Confidence checks @@ -644,12 +575,12 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // Then XCTAssertEqual(viewModel.shipments.count, 1) XCTAssertEqual(viewModel.shipments[0].contents.count, 3) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 2) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 1) - XCTAssertEqual(viewModel.shipments[0].contents[2].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[2].packageItem.quantity, 3) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 2) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 1) + XCTAssertEqual(viewModel.shipments[0].contents[2].orderItemID, items[2].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[2].quantity, 3) } func test_mergeAllUnfulfilledShipments_updates_shipments_correctly_when_there_exists_a_purchased_shipment() throws { @@ -658,15 +589,14 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1), sampleItem(id: 3, weight: 4, value: 5, quantity: 3)] - let shippingLabelData = WooShippingLabelData(currentOrderLabels: [ShippingLabelPurchase.fake().copy(shipmentID: "2")]) - let config = WooShippingConfig(siteID: 123, shipments: [ - "1": [WooShippingShipmentItem(id: 1, subItems: ["sub-1", "sub-2"])], - "2": [WooShippingShipmentItem(id: 2, subItems: [])], - "3": [WooShippingShipmentItem(id: 3, subItems: ["sub-1", "sub-2", "sub-3"])] - ], shippingLabelData: shippingLabelData) + let shipments = [ + createShipment(with: [items[0]]), + createShipment(with: [items[1]], isPurchased: true), + createShipment(with: [items[2]]) + ] + let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: config, - items: items, + shipments: shipments, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -679,15 +609,15 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { // Then XCTAssertEqual(viewModel.shipments.count, 2) XCTAssertEqual(viewModel.shipments[0].contents.count, 2) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.orderItemID, items[0].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[0].packageItem.quantity, 2) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.orderItemID, items[2].orderItemID) - XCTAssertEqual(viewModel.shipments[0].contents[1].packageItem.quantity, 3) + XCTAssertEqual(viewModel.shipments[0].contents[0].orderItemID, items[0].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[0].quantity, 2) + XCTAssertEqual(viewModel.shipments[0].contents[1].orderItemID, items[2].orderItemID) + XCTAssertEqual(viewModel.shipments[0].contents[1].quantity, 3) XCTAssertEqual(viewModel.shipments[1].contents.count, 1) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.orderItemID, items[1].orderItemID) - XCTAssertEqual(viewModel.shipments[1].contents[0].packageItem.quantity, 1) + XCTAssertEqual(viewModel.shipments[1].contents[0].orderItemID, items[1].orderItemID) + XCTAssertEqual(viewModel.shipments[1].contents[0].quantity, 1) } // MARK: - `enableDoneButton` @@ -699,8 +629,7 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 3), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], stores: stores, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) @@ -716,14 +645,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 3), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], stores: stores, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then @@ -752,14 +680,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 3), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], stores: stores, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) // Then @@ -788,14 +715,13 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { let items = [sampleItem(id: 1, weight: 5, value: 10, quantity: 3), sampleItem(id: 2, weight: 3, value: 2.5, quantity: 1)] let viewModel = WooShippingSplitShipmentsViewModel(order: sampleOrder, - config: WooShippingConfig.fake(), - items: items, + shipments: [createShipment(with: items)], stores: stores, currencySettings: currencySettings, shippingSettingsService: shippingSettingsService) // When - viewModel.shipments.first?.contents.first?.childItemRows.first?.handleTap() + viewModel.shipments.first?.splitShipmentViewModels.first?.childItemRows.first?.handleTap() viewModel.moveSelectedItems(to: .newShipment) viewModel.undoMovingItems() @@ -805,6 +731,14 @@ final class WooShippingSplitShipmentsViewModelTests: XCTestCase { } private extension WooShippingSplitShipmentsViewModelTests { + func createShipment(with items: [ShippingLabelPackageItem], isPurchased: Bool = false) -> Shipment { + Shipment(contents: items, + isPurchased: isPurchased, + currency: sampleOrder.currency, + currencySettings: currencySettings, + shippingSettingsService: shippingSettingsService) + } + func sampleItem(id: Int64, weight: Double, value: Double, quantity: Decimal) -> ShippingLabelPackageItem { ShippingLabelPackageItem(productOrVariationID: id, orderItemID: id, From 808e32e708d23542f9d7dd7a6a5c75e3a22429a1 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 20:40:44 +0700 Subject: [PATCH 5/7] Restore previews --- .../WooShippingSplitShipmentsDetailView.swift | 22 ++++++++++++++++++ .../WooShippingSplitShipmentsRow.swift | 23 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift index ec5eec45776..6ce73eddc2b 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift @@ -448,3 +448,25 @@ fileprivate extension WooShippingSplitShipmentsDetailView { } } } + +#if DEBUG +#Preview { + WooShippingSplitShipmentsDetailView(viewModel: WooShippingSplitShipmentsViewModel( + order: ShippingLabelSampleData.sampleOrder(), + shipments: [ + WooShippingSplitShipmentsViewModel.Shipment(contents: [ShippingLabelPackageItem(productOrVariationID: 1, + orderItemID: 12, + name: "Shirt", + weight: 0.5, + quantity: 2, + value: 9.99, + dimensions: ProductDimensions(length: "", + width: "", + height: ""), + attributes: [], + imageURL: nil)], currency: "$", + currencySettings: ServiceLocator.currencySettings, + shippingSettingsService: ServiceLocator.shippingSettingsService) + ])) +} +#endif diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift index de962bfa0f2..9ae5d53fe59 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsRow.swift @@ -42,3 +42,26 @@ private extension WooShippingSplitShipmentsRow { comment: "Title for button in shipping label creation to start split shipments flow.") } } + +#if DEBUG +#Preview { + WooShippingSplitShipmentsRow(viewModel: WooShippingSplitShipmentsViewModel( + order: ShippingLabelSampleData.sampleOrder(), + shipments: [ + WooShippingSplitShipmentsViewModel.Shipment(contents: [ShippingLabelPackageItem(productOrVariationID: 1, + orderItemID: 12, + name: "Shirt", + weight: 0.5, + quantity: 2, + value: 9.99, + dimensions: ProductDimensions(length: "", + width: "", + height: ""), + attributes: [], + imageURL: nil)], currency: "$", + currencySettings: ServiceLocator.currencySettings, + shippingSettingsService: ServiceLocator.shippingSettingsService) + ])) + .padding() +} +#endif From 4a4ebf20d3219839f2af2410e9dc20227b7d8c24 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 21:35:58 +0700 Subject: [PATCH 6/7] Fix unit test failure --- .../WooShippingCreateLabelsViewModelTests.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModelTests.swift index 92306f6281f..b746b974e24 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModelTests.swift @@ -202,7 +202,6 @@ final class WooShippingCreateLabelsViewModelTests: XCTestCase { viewModel.state != .loading } XCTAssertFalse(loadedConfig) - XCTAssertNil(viewModel.splitShipmentsViewModel) } func test_shipping_config_is_loaded_if_order_contains_more_than_one_item() { @@ -240,7 +239,6 @@ final class WooShippingCreateLabelsViewModelTests: XCTestCase { viewModel.state != .loading } XCTAssertTrue(loadedConfig) - XCTAssertNotNil(viewModel.splitShipmentsViewModel) } func test_origin_unverified_state_is_correct() { From e85fabec1842ffbf82d1b11f7be2ab5c67fb14a1 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 2 Apr 2025 21:53:07 +0700 Subject: [PATCH 7/7] Revert change to splitShipmentsViewModel --- .../WooShippingSplitShipmentsDetailView.swift | 1 + .../WooShippingCreateLabelsView.swift | 4 ++-- .../WooShippingCreateLabelsViewModel.swift | 14 ++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift index 6ce73eddc2b..8d31d192a45 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Split Shipments/WooShippingSplitShipmentsDetailView.swift @@ -249,6 +249,7 @@ private extension WooShippingSplitShipmentsDetailView { } .font(.subheadline) } + .foregroundStyle(Color(.text)) } .padding(Layout.contentPadding) .if(otherShipment == shipmentToMergeInto) { view in 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 db44e8f581b..ce5858ec721 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 @@ -105,8 +105,8 @@ private extension WooShippingCreateLabelsView { WooShippingPostPurchaseView(viewModel: postPurchase) } - if !viewModel.canViewLabel { - WooShippingSplitShipmentsRow(viewModel: viewModel.splitShipmentsViewModel) + if !viewModel.canViewLabel, let splitShipmentsViewModel = viewModel.splitShipmentsViewModel { + WooShippingSplitShipmentsRow(viewModel: splitShipmentsViewModel) } WooShippingItems(viewModel: viewModel.items) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift index 871b27d0d1f..1c5c79a2660 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift @@ -55,7 +55,13 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { typealias Shipment = WooShippingSplitShipmentsViewModel.Shipment - @Published private(set) var shipments: [Shipment] + private var shipments: [Shipment] { + didSet { + splitShipmentsViewModel = WooShippingSplitShipmentsViewModel(order: order, + shipments: shipments, + stores: stores) + } + } /// Selected package data for the shipping label. @Published private(set) var selectedPackage: WooShippingPackageDataRepresentable? @@ -67,11 +73,7 @@ final class WooShippingCreateLabelsViewModel: ObservableObject { private(set) var shippingService: WooShippingServiceViewModel? /// View model for split shipments. - var splitShipmentsViewModel: WooShippingSplitShipmentsViewModel { - return WooShippingSplitShipmentsViewModel(order: order, - shipments: shipments, - stores: stores) - } + private(set) var splitShipmentsViewModel: WooShippingSplitShipmentsViewModel? /// Selected shipping rate when creating a shipping label. @Published private var selectedRate: WooShippingSelectedRate?