diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsViewModel.swift index 8802bbfad4b..2ffa96aba85 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsViewModel.swift @@ -5,7 +5,7 @@ import WooFoundation /// Provides view data for `WooShippingItems`. /// final class WooShippingItemsViewModel: ObservableObject { - private let order: Order + private let orderItems: [OrderItem] private let currencyFormatter: CurrencyFormatter /// Label with the total number of items to ship. @@ -17,9 +17,9 @@ final class WooShippingItemsViewModel: ObservableObject { /// View models for rows of items to ship. @Published var itemRows: [WooShippingItemRowViewModel] = [] - init(order: Order, + init(orderItems: [OrderItem], currencySettings: CurrencySettings = ServiceLocator.currencySettings) { - self.order = order + self.orderItems = orderItems self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings) configureSectionHeader() @@ -44,9 +44,7 @@ private extension WooShippingItemsViewModel { /// Generates a label with the total number of items to ship. /// func generateItemsCountLabel() -> String { - let itemsCount = order.items - .map { $0.quantity } - .reduce(0, +) + let itemsCount = orderItems.map(\.quantity).reduce(0, +) return Localization.itemsCount(itemsCount) } @@ -55,7 +53,8 @@ private extension WooShippingItemsViewModel { /// func generateItemsDetailLabel() -> String { let formattedWeight = "1 kg" // TODO-13550: Get the total weight (each product/variation * item quantity) and weight unit - let formattedPrice = currencyFormatter.formatAmount(order.total) ?? order.total + let itemsTotal = orderItems.map { $0.price.decimalValue * $0.quantity }.reduce(0, +) + let formattedPrice = currencyFormatter.formatAmount(itemsTotal) ?? itemsTotal.description return "\(formattedWeight) • \(formattedPrice)" } @@ -63,13 +62,13 @@ private extension WooShippingItemsViewModel { /// Generates an item row view model for each order item. /// func generateItemRows() -> [WooShippingItemRowViewModel] { - order.items.map { item in - return WooShippingItemRowViewModel(imageUrl: nil, // TODO-13550: Get the product/variation imageURL - quantityLabel: item.quantity.description, - name: item.name, - detailsLabel: generateItemRowDetailsLabel(for: item), - weightLabel: "", // TODO-13550: Get the product/variation weight - priceLabel: currencyFormatter.formatAmount(item.total) ?? item.total) + orderItems.map { item in + WooShippingItemRowViewModel(imageUrl: nil, // TODO-13550: Get the product/variation imageURL + quantityLabel: item.quantity.description, + name: item.name, + detailsLabel: generateItemRowDetailsLabel(for: item), + weightLabel: "", // TODO-13550: Get the product/variation weight + priceLabel: currencyFormatter.formatAmount(item.price.decimalValue) ?? item.price.description) } } 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 9b4f4d5bbe1..22ace00ff26 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 @@ -4,13 +4,10 @@ import Yosemite /// Provides view data for `WooShippingCreateLabelsView`. /// final class WooShippingCreateLabelsViewModel: ObservableObject { - private let order: Order - /// View model for the items to ship. @Published private(set) var items: WooShippingItemsViewModel init(order: Order) { - self.order = order - self.items = WooShippingItemsViewModel(order: order) + self.items = WooShippingItemsViewModel(orderItems: order.items) } } diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingItemsViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingItemsViewModelTests.swift index c3d6e580b55..9ba80c2233f 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingItemsViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Shipping Label/WooShipping Create Shipping Labels/WooShippingItemsViewModelTests.swift @@ -13,50 +13,58 @@ final class WooShippingItemsViewModelTests: XCTestCase { func test_inits_with_expected_values_from_order_items() throws { // Given - let order = Order.fake().copy(total: "22.5", items: [OrderItem.fake().copy(name: "Shirt", - quantity: 1, - total: "20", - attributes: [OrderItemAttribute.fake().copy(value: "Red")]), - OrderItem.fake().copy(quantity: 1)]) + let orderItems = [OrderItem.fake().copy(name: "Shirt", + quantity: 1, + price: 10, + attributes: [OrderItemAttribute.fake().copy(value: "Red")]), + OrderItem.fake().copy(quantity: 1, price: 2.5)] // When - let viewModel = WooShippingItemsViewModel(order: order, currencySettings: currencySettings) + let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings) // Then // Section header labels have expected values assertEqual("2 items", viewModel.itemsCountLabel) - assertEqual("1 kg • $22.50", viewModel.itemsDetailLabel) + assertEqual("1 kg • $12.50", viewModel.itemsDetailLabel) // Section rows have expected values assertEqual(2, viewModel.itemRows.count) let firstItem = try XCTUnwrap(viewModel.itemRows.first) assertEqual("Shirt", firstItem.name) assertEqual("1", firstItem.quantityLabel) - assertEqual("$20.00", firstItem.priceLabel) + assertEqual("$10.00", firstItem.priceLabel) assertEqual("Red", firstItem.detailsLabel) } func test_total_items_count_handles_items_with_quantity_greater_than_one() { // Given - let order = Order.fake().copy(total: "22.5", items: [OrderItem.fake().copy(name: "Shirt", quantity: 2, total: "20"), OrderItem.fake().copy(quantity: 1)]) + let orderItems = [OrderItem.fake().copy(quantity: 2), OrderItem.fake().copy(quantity: 1)] // When - let viewModel = WooShippingItemsViewModel(order: order, currencySettings: currencySettings) + let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings) // Then assertEqual("3 items", viewModel.itemsCountLabel) } + func test_total_items_details_handles_total_price_for_items_with_quantity_greater_than_one() { + // Given + let orderItems = [OrderItem.fake().copy(quantity: 2, price: 10), OrderItem.fake().copy(quantity: 1, price: 2.5)] + + // When + let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings) + + // Then + assertEqual("1 kg • $22.50", viewModel.itemsDetailLabel) + } + func test_item_row_details_label_handles_items_with_multiple_attributes() throws { // Given - let order = Order.fake().copy(total: "22.5", items: [OrderItem.fake().copy(name: "Shirt", - quantity: 2, - total: "20", - attributes: [OrderItemAttribute.fake().copy(value: "Red"), - OrderItemAttribute.fake().copy(value: "Small")])]) + let orderItems = [OrderItem.fake().copy(attributes: [OrderItemAttribute.fake().copy(value: "Red"), + OrderItemAttribute.fake().copy(value: "Small")])] // When - let viewModel = WooShippingItemsViewModel(order: order, currencySettings: currencySettings) + let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings) // Then let firstItem = try XCTUnwrap(viewModel.itemRows.first)