diff --git a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift index 8c430b3bd42..0aea6c42528 100644 --- a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift +++ b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift @@ -99,6 +99,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService { return buildConfig == .localDeveloper || buildConfig == .alpha case .pointOfSaleOrdersi1: return buildConfig == .localDeveloper || buildConfig == .alpha + case .pointOfSaleOrdersi2: + return buildConfig == .localDeveloper || buildConfig == .alpha default: return true } diff --git a/Modules/Sources/Experiments/FeatureFlag.swift b/Modules/Sources/Experiments/FeatureFlag.swift index 94ef3bf0e81..d2be4d0fd03 100644 --- a/Modules/Sources/Experiments/FeatureFlag.swift +++ b/Modules/Sources/Experiments/FeatureFlag.swift @@ -203,4 +203,8 @@ public enum FeatureFlag: Int { /// Enables displaying Point Of Sale details in order list and order details /// case pointOfSaleOrdersi1 + + /// Enables displaying Point Of Sale as a filter in order list + /// + case pointOfSaleOrdersi2 } diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/OrderListSyncBackgroundTask.swift b/WooCommerce/Classes/Tools/BackgroundTasks/OrderListSyncBackgroundTask.swift index 25f46431b5c..aac7cf3be61 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/OrderListSyncBackgroundTask.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/OrderListSyncBackgroundTask.swift @@ -77,6 +77,7 @@ private struct CurrentOrderListSyncUseCase { dateRange: settings.dateRangeFilter, product: settings.productFilter, customer: settings.customerFilter, + salesChannel: nil, // TODO: Filter persistence WOOMOB-712 numberOfActiveFilters: settings.numberOfActiveFilters()) continuation.resume(returning: filters) case .failure: diff --git a/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift b/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift index dfa06b14a9d..4047f1018e1 100644 --- a/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift @@ -92,6 +92,8 @@ enum FilterListValueSelectorConfig { case products(siteID: Int64) // Filter list selector for customer case customer(siteID: Int64) + // Filter list selector for sales channel + case salesChannel } @@ -297,6 +299,10 @@ private extension FilterListViewController { self.listSelector.reloadData() } self.listSelector.navigationController?.pushViewController(statusesFilterVC, animated: true) + case .salesChannel: + // TODO: Make OrderSalesChannelFilterViewController, and handle filtering selection WOOMOB-711 + let emptyViewController = EmptyStateViewController(style: .list) + self.listSelector.navigationController?.pushViewController(emptyViewController, animated: true) case .ordersDateRange: let selectedOrderFilter = selected.selectedValue as? OrderDateRangeFilter let datesFilterVC = OrderDatesFilterViewController(selected: selectedOrderFilter) { dateRangeFilter in diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift index dbe57c2fe36..1328560bf60 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift @@ -13,6 +13,7 @@ final class FilterOrderListViewModel: FilterListViewModel { let dateRange: OrderDateRangeFilter? let product: FilterOrdersByProduct? let customer: CustomerFilter? + let salesChannel: SalesChannelFilter? let numberOfActiveFilters: Int @@ -21,6 +22,7 @@ final class FilterOrderListViewModel: FilterListViewModel { dateRange = nil product = nil customer = nil + salesChannel = nil numberOfActiveFilters = 0 } @@ -28,11 +30,13 @@ final class FilterOrderListViewModel: FilterListViewModel { dateRange: OrderDateRangeFilter?, product: FilterOrdersByProduct?, customer: CustomerFilter?, + salesChannel: SalesChannelFilter?, numberOfActiveFilters: Int) { self.orderStatus = orderStatus self.dateRange = dateRange self.product = product self.customer = customer + self.salesChannel = salesChannel self.numberOfActiveFilters = numberOfActiveFilters } @@ -50,6 +54,11 @@ final class FilterOrderListViewModel: FilterListViewModel { if let customer = customer { readable.append(customer.description) } + + if let salesChannel = salesChannel { + readable.append(salesChannel.description) + } + return readable.joined(separator: ", ") } } @@ -66,6 +75,7 @@ final class FilterOrderListViewModel: FilterListViewModel { private let dateRangeFilterViewModel: FilterTypeViewModel private let productFilterViewModel: FilterTypeViewModel private let customerFilterViewModel: FilterTypeViewModel + private let salesChannelFilterViewModel: FilterTypeViewModel private let siteID: Int64 private let stores: StoresManager @@ -87,13 +97,23 @@ final class FilterOrderListViewModel: FilterListViewModel { dateRangeFilterViewModel = OrderListFilter.dateRange.createViewModel(filters: filters, allowedStatuses: allowedStatuses) productFilterViewModel = OrderListFilter.product(siteID: siteID).createViewModel(filters: filters, allowedStatuses: allowedStatuses) customerFilterViewModel = OrderListFilter.customer(siteID: siteID).createViewModel(filters: filters, allowedStatuses: allowedStatuses) + salesChannelFilterViewModel = OrderListFilter.salesChannel.createViewModel(filters: filters, allowedStatuses: allowedStatuses) self.siteID = siteID self.stores = stores self.analytics = analytics shouldShowHistory = featureFlagService.isFeatureFlagEnabled(.filterHistoryOnOrderAndProductLists) - filterTypeViewModels = [orderStatusFilterViewModel, dateRangeFilterViewModel, customerFilterViewModel, productFilterViewModel] + var allFilterViewModels = [orderStatusFilterViewModel, + dateRangeFilterViewModel, + customerFilterViewModel, + productFilterViewModel] + + if featureFlagService.isFeatureFlagEnabled(.pointOfSaleOrdersi2) { + allFilterViewModels.append(salesChannelFilterViewModel) + } + + filterTypeViewModels = allFilterViewModels } var criteria: Filters { @@ -101,11 +121,13 @@ final class FilterOrderListViewModel: FilterListViewModel { let dateRange = dateRangeFilterViewModel.selectedValue as? OrderDateRangeFilter ?? nil let product = productFilterViewModel.selectedValue as? FilterOrdersByProduct ?? nil let customer = customerFilterViewModel.selectedValue as? CustomerFilter ?? nil + let salesChannel = salesChannelFilterViewModel.selectedValue as? SalesChannelFilter ?? nil let numberOfActiveFilters = filterTypeViewModels.numberOfActiveFilters return Filters(orderStatus: orderStatus, dateRange: dateRange, product: product, customer: customer, + salesChannel: salesChannel, numberOfActiveFilters: numberOfActiveFilters) } @@ -120,6 +142,7 @@ final class FilterOrderListViewModel: FilterListViewModel { dateRange: item.dateRangeFilter, product: item.productFilter, customer: item.customerFilter, + salesChannel: nil, // TODO: Filter persistence WOOMOB-712 numberOfActiveFilters: item.numberOfActiveFilters()) } continuation.resume(returning: filters) @@ -198,6 +221,7 @@ extension FilterOrderListViewModel { case dateRange case product(siteID: Int64) case customer(siteID: Int64) + case salesChannel } } @@ -212,6 +236,8 @@ private extension FilterOrderListViewModel.OrderListFilter { return Localization.rowTitleProduct case .customer: return Localization.rowCustomer + case .salesChannel: + return Localization.rowSalesChannel } } } @@ -235,6 +261,10 @@ extension FilterOrderListViewModel.OrderListFilter { return FilterTypeViewModel(title: title, listSelectorConfig: .customer(siteID: siteID), selectedValue: filters.customer) + case .salesChannel: + return FilterTypeViewModel(title: title, + listSelectorConfig: .salesChannel, + selectedValue: filters.salesChannel) } } } @@ -281,20 +311,39 @@ extension FilterOrdersByProduct: FilterType { // MARK: - Constants private extension FilterOrderListViewModel { enum Localization { - static let filterActionTitle = NSLocalizedString("Show Orders", comment: "Button title for applying filters to a list of orders.") + static let filterActionTitle = NSLocalizedString( + "filterOrderListViewModel.OrderListFilter.filterActionTitle", + value: "Show Orders", + comment: "Button title for applying filters to a list of orders.") } } private extension FilterOrderListViewModel.OrderListFilter { enum Localization { - static let rowTitleOrderStatus = NSLocalizedString("Order Status", comment: "Row title for filtering orders by order status.") - static let rowTitleDateRange = NSLocalizedString("Date Range", comment: "Row title for filtering orders by date range.") - static let rowTitleProduct = NSLocalizedString("filterOrderListViewModel.OrderListFilter.rowTitleProduct", - value: "Product", - comment: "Row title for filtering orders by Product.") - static let rowCustomer = NSLocalizedString("filterOrderListViewModel.OrderListFilter.rowCustomer", - value: "Customer", - comment: "Row title for filtering orders by customer.") + static let rowTitleOrderStatus = NSLocalizedString( + "filterOrderListViewModel.OrderListFilter.rowTitleOrderStatus", + value: "Order Status", + comment: "Row title for filtering orders by order status.") + + static let rowTitleDateRange = NSLocalizedString( + "filterOrderListViewModel.OrderListFilter.rowTitleDateRange", + value: "Date Range", + comment: "Row title for filtering orders by date range.") + + static let rowTitleProduct = NSLocalizedString( + "filterOrderListViewModel.OrderListFilter.rowTitleProduct", + value: "Product", + comment: "Row title for filtering orders by Product.") + + static let rowCustomer = NSLocalizedString( + "filterOrderListViewModel.OrderListFilter.rowCustomer", + value: "Customer", + comment: "Row title for filtering orders by customer.") + + static let rowSalesChannel = NSLocalizedString( + "filterOrderListViewModel.OrderListFilter.rowSalesChannel", + value: "Sales Channel", + comment: "Row title for filtering orders by sales channel.") } } @@ -322,3 +371,20 @@ extension CustomerFilter: FilterType { /// Whether the filter is set to a non-empty value. var isActive: Bool { true } } + +extension FilterOrderListViewModel { + enum SalesChannelFilter: FilterType { + case pointOfSale + + var description: String { + switch self { + case .pointOfSale: + return "POS" + } + } + + var isActive: Bool { + return true + } + } +} diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersRootViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersRootViewController.swift index 7b25dd5113d..55a2ab6da7a 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersRootViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersRootViewController.swift @@ -448,6 +448,7 @@ private extension OrdersRootViewController { dateRange: settings.dateRangeFilter, product: settings.productFilter, customer: settings.customerFilter, + salesChannel: nil, // TODO: Filter persistence WOOMOB-712 numberOfActiveFilters: settings.numberOfActiveFilters()) case .failure(let error): print("It was not possible to sync local orders settings: \(String(describing: error))") diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Orders/Filters/FilterOrderListViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Orders/Filters/FilterOrderListViewModelTests.swift index 1e98f785464..868a6a7d2ef 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Orders/Filters/FilterOrderListViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Orders/Filters/FilterOrderListViewModelTests.swift @@ -15,6 +15,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 0) XCTAssertEqual(viewModel.criteria, expectedCriteria) } @@ -25,6 +26,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: OrderDateRangeFilter(filter: .today), product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: CustomerFilter(customer: Customer.fake().copy(customerID: 1)), + salesChannel: nil, numberOfActiveFilters: 4) // When @@ -41,6 +43,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: OrderDateRangeFilter(filter: .last7Days), product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: CustomerFilter(customer: Customer.fake().copy(customerID: 1)), + salesChannel: nil, numberOfActiveFilters: 4) // When @@ -52,6 +55,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 0) XCTAssertEqual(viewModel.criteria, expectedCriteria) } @@ -64,6 +68,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: OrderDateRangeFilter(filter: .today), product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: CustomerFilter(customer: Customer.fake().copy(customerID: 1)), + salesChannel: nil, numberOfActiveFilters: 4) // When @@ -100,6 +105,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: OrderDateRangeFilter(filter: .today), product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: CustomerFilter(customer: Customer.fake().copy(customerID: 1)), + salesChannel: nil, numberOfActiveFilters: 4) let viewModel = FilterOrderListViewModel(filters: filters, allowedStatuses: [], @@ -116,11 +122,13 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: result1.dateRangeFilter, product: result1.productFilter, customer: result1.customerFilter, + salesChannel: nil, numberOfActiveFilters: result1.numberOfActiveFilters()), FilterOrderListViewModel.Filters(orderStatus: result2.orderStatusesFilter, dateRange: result2.dateRangeFilter, product: result2.productFilter, customer: result2.customerFilter, + salesChannel: nil, numberOfActiveFilters: result2.numberOfActiveFilters()) ]) } @@ -144,6 +152,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: OrderDateRangeFilter(filter: .today), product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: CustomerFilter(customer: Customer.fake().copy(customerID: 1)), + salesChannel: nil, numberOfActiveFilters: 4) let viewModel = FilterOrderListViewModel(filters: filters, allowedStatuses: [], @@ -179,6 +188,7 @@ final class FilterOrderListViewModelTests: XCTestCase { dateRange: OrderDateRangeFilter(filter: .today), product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: CustomerFilter(customer: Customer.fake().copy(customerID: 1)), + salesChannel: nil, numberOfActiveFilters: 4) let viewModel = FilterOrderListViewModel(filters: filters, allowedStatuses: [], diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListSyncActionUseCaseTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListSyncActionUseCaseTests.swift index 33e9ce20ebf..7745cd001fb 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListSyncActionUseCaseTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListSyncActionUseCaseTests.swift @@ -28,6 +28,7 @@ final class OrderListSyncActionUseCaseTests: XCTestCase { dateRange: nil, product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let useCase = OrderListSyncActionUseCase(siteID: siteID, filters: filters) @@ -60,6 +61,7 @@ final class OrderListSyncActionUseCaseTests: XCTestCase { dateRange: nil, product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let useCase = OrderListSyncActionUseCase(siteID: siteID, filters: filters) @@ -144,6 +146,7 @@ final class OrderListSyncActionUseCaseTests: XCTestCase { dateRange: nil, product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let useCase = OrderListSyncActionUseCase(siteID: siteID, filters: filters) @@ -201,6 +204,7 @@ final class OrderListSyncActionUseCaseTests: XCTestCase { dateRange: nil, product: FilterOrdersByProduct(id: 1, name: "Sample product"), customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let useCase = OrderListSyncActionUseCase(siteID: siteID, filters: filters) diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListViewModelTests.swift index 61796f147d2..2ccdfa45ed0 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Orders/OrderListViewModelTests.swift @@ -50,6 +50,7 @@ final class OrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let viewModel = OrderListViewModel(siteID: siteID, storageManager: storageManager, @@ -100,6 +101,7 @@ final class OrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let viewModel = OrderListViewModel(siteID: siteID, storageManager: storageManager, @@ -136,6 +138,7 @@ final class OrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 1) let viewModel = OrderListViewModel(siteID: siteID, storageManager: storageManager, @@ -323,6 +326,7 @@ final class OrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 1)) // Assert @@ -335,6 +339,7 @@ final class OrderListViewModelTests: XCTestCase { dateRange: nil, product: nil, customer: nil, + salesChannel: nil, numberOfActiveFilters: 0) let notificationCenter = NotificationCenter() let viewModel = OrderListViewModel(siteID: siteID,