From 595f7cd43b407b18824e96d97242c0ca4783cc7b Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 8 Sep 2025 21:16:08 +0700 Subject: [PATCH 1/2] remove pointOfSaleReceipts flag --- .../DefaultFeatureFlagService.swift | 2 - Modules/Sources/Experiments/FeatureFlag.swift | 4 - .../PointOfSaleOrderController.swift | 22 ++---- .../PointOfSaleOrderControllerTests.swift | 77 +++---------------- 4 files changed, 17 insertions(+), 88 deletions(-) diff --git a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift index 08d57cb8f29..51a18316497 100644 --- a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift +++ b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift @@ -84,8 +84,6 @@ public struct DefaultFeatureFlagService: FeatureFlagService { return false case .inventoryProductLabelsInPOS: return false - case .pointOfSaleReceipts: - return true case .productImageOptimizedHandling: return true case .pointOfSaleAsATabi2: diff --git a/Modules/Sources/Experiments/FeatureFlag.swift b/Modules/Sources/Experiments/FeatureFlag.swift index 797ad5e0495..47ea6512a97 100644 --- a/Modules/Sources/Experiments/FeatureFlag.swift +++ b/Modules/Sources/Experiments/FeatureFlag.swift @@ -179,10 +179,6 @@ public enum FeatureFlag: Int { /// case inventoryProductLabelsInPOS - /// Enables sending POS specific email receipts for eligible stores - /// - case pointOfSaleReceipts - /// Enables displaying POS as a tab in the tab bar for stores in eligible countries /// case pointOfSaleAsATabi2 diff --git a/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift b/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift index 091d09a5476..e8cf5460c60 100644 --- a/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift +++ b/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift @@ -110,7 +110,7 @@ protocol PointOfSaleOrderControllerProtocol { @MainActor func sendReceipt(recipientEmail: String) async throws { - var isEligibleForPOSReceipt: Bool? + var isEligibleForPOSReceipt: Bool = false do { guard let order else { throw PointOfSaleOrderControllerError.noOrder @@ -118,21 +118,15 @@ protocol PointOfSaleOrderControllerProtocol { try await orderService.updatePOSOrder(order: order, recipientEmail: recipientEmail) - let posReceiptEligibility: Bool - if featureFlagService.isFeatureFlagEnabled(.pointOfSaleReceipts) { - posReceiptEligibility = isPluginSupported( - .wooCommerce, - minimumVersion: POSReceiptEligibilityConstants.wcPluginMinimumVersion, - siteID: order.siteID - ) - } else { - posReceiptEligibility = false - } - isEligibleForPOSReceipt = posReceiptEligibility + isEligibleForPOSReceipt = isPluginSupported( + .wooCommerce, + minimumVersion: POSReceiptEligibilityConstants.wcPluginMinimumVersion, + siteID: order.siteID + ) - try await receiptService.sendReceipt(order: order, recipientEmail: recipientEmail, isEligibleForPOSReceipt: posReceiptEligibility) + try await receiptService.sendReceipt(order: order, recipientEmail: recipientEmail, isEligibleForPOSReceipt: isEligibleForPOSReceipt) - analytics.track(.receiptEmailSuccess, withProperties: ["eligible_for_pos_receipt": posReceiptEligibility]) + analytics.track(.receiptEmailSuccess, withProperties: ["eligible_for_pos_receipt": isEligibleForPOSReceipt]) } catch { let properties = [ "eligible_for_pos_receipt": isEligibleForPOSReceipt diff --git a/WooCommerce/WooCommerceTests/POS/Controllers/PointOfSaleOrderControllerTests.swift b/WooCommerce/WooCommerceTests/POS/Controllers/PointOfSaleOrderControllerTests.swift index 8be5311ce21..e1170b75861 100644 --- a/WooCommerce/WooCommerceTests/POS/Controllers/PointOfSaleOrderControllerTests.swift +++ b/WooCommerce/WooCommerceTests/POS/Controllers/PointOfSaleOrderControllerTests.swift @@ -182,11 +182,8 @@ struct PointOfSaleOrderControllerTests { @Test func sendReceipt_when_there_is_no_order_then_will_not_trigger() async throws { // Given - let mockFeatureFlagService = MockFeatureFlagService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true let sut = PointOfSaleOrderController(orderService: mockOrderService, - receiptService: mockReceiptService, - featureFlagService: mockFeatureFlagService) + receiptService: mockReceiptService) let email = "test@example.com" // When @@ -202,11 +199,8 @@ struct PointOfSaleOrderControllerTests { @Test func sendReceipt_calls_both_updateOrder_and_sendReceipt() async throws { // Given - let mockFeatureFlagService = MockFeatureFlagService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true let sut = PointOfSaleOrderController(orderService: mockOrderService, - receiptService: mockReceiptService, - featureFlagService: mockFeatureFlagService) + receiptService: mockReceiptService) let order = Order.fake() let recipientEmail = "test@fake.com" mockOrderService.orderToReturn = order @@ -638,13 +632,9 @@ struct PointOfSaleOrderControllerTests { version: "10.0.0-dev", active: true)) - let mockFeatureFlagService = MockFeatureFlagService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true - let sut = PointOfSaleOrderController(orderService: orderService, receiptService: receiptService, analytics: analytics, - featureFlagService: mockFeatureFlagService, pluginsService: mockPluginsService) let order = Order.fake() orderService.orderToReturn = order @@ -664,12 +654,9 @@ struct PointOfSaleOrderControllerTests { @Test func sendReceipt_without_order_tracks_failure_without_eligible_for_pos_receipt() async throws { // Given - let mockFeatureFlagService = MockFeatureFlagService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true let sut = PointOfSaleOrderController(orderService: orderService, receiptService: receiptService, - analytics: analytics, - featureFlagService: mockFeatureFlagService) + analytics: analytics) // When do { @@ -677,7 +664,7 @@ struct PointOfSaleOrderControllerTests { } catch { // Then let indexOfEvent = try #require(analyticsProvider.receivedEvents.firstIndex(where: { $0 == "receipt_email_failed" })) - #expect(analyticsProvider.receivedProperties[indexOfEvent]["eligible_for_pos_receipt"] == nil) + #expect(analyticsProvider.receivedProperties[indexOfEvent]["eligible_for_pos_receipt"] as? Bool == false) } } @@ -689,12 +676,9 @@ struct PointOfSaleOrderControllerTests { version: "10.0.0-dev", active: true)) - let mockFeatureFlagService = MockFeatureFlagService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true let sut = PointOfSaleOrderController(orderService: orderService, receiptService: receiptService, analytics: analytics, - featureFlagService: mockFeatureFlagService, pluginsService: mockPluginsService) receiptService.sendReceiptResult = .failure(DotcomError.unknown(code: "test_error", message: "Test error")) @@ -723,13 +707,11 @@ struct PointOfSaleOrderControllerTests { struct ReceiptTests { private let mockOrderService = MockPOSOrderService() - @Test("Eligible core plugin versions with feature flag enabled", arguments: Constants.eligibleWCPluginVersions) - func sendReceipt_when_feature_flag_enabled_and_eligible_plugin_version_sets_isEligibleForPOSReceipt_true(wcPluginVersion: String) async throws { + @Test("Eligible core plugin versions", arguments: Constants.eligibleWCPluginVersions) + func sendReceipt_when_eligible_plugin_version_sets_isEligibleForPOSReceipt_true(wcPluginVersion: String) async throws { // Given let mockReceiptService = MockReceiptService() - let mockFeatureFlagService = MockFeatureFlagService() let mockPluginsService = MockPluginsService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true mockPluginsService.setMockPlugin(.wooCommerce, systemPlugin: SystemPlugin.fake().copy(plugin: "woocommerce/woocommerce.php", version: wcPluginVersion, @@ -738,7 +720,6 @@ struct PointOfSaleOrderControllerTests { let sut = PointOfSaleOrderController(orderService: mockOrderService, receiptService: mockReceiptService, analytics: ServiceLocator.analytics, - featureFlagService: mockFeatureFlagService, pluginsService: mockPluginsService) mockOrderService.orderToReturn = Order.fake() @@ -753,47 +734,11 @@ struct PointOfSaleOrderControllerTests { #expect(mockReceiptService.spyIsEligibleForPOSReceipt == true) } - @Test( - "All core plugin versions with feature flag disabled", - arguments: Constants.eligibleWCPluginVersions + Constants.ineligibleWCPluginVersions - ) - func sendReceipt_when_feature_flag_disabled_and_eligible_plugin_version_sets_isEligibleForPOSReceipt_false(wcPluginVersion: String) async throws { - // Given - let mockReceiptService = MockReceiptService() - let mockFeatureFlagService = MockFeatureFlagService() - let mockPluginsService = MockPluginsService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = false - // Plugin setup is irrelevant when feature flag is disabled - mockPluginsService.setMockPlugin(.wooCommerce, - systemPlugin: SystemPlugin.fake().copy(plugin: "woocommerce/woocommerce.php", - version: wcPluginVersion, - active: true)) - - let sut = PointOfSaleOrderController(orderService: mockOrderService, - receiptService: mockReceiptService, - analytics: ServiceLocator.analytics, - featureFlagService: mockFeatureFlagService, - pluginsService: mockPluginsService) - mockOrderService.orderToReturn = Order.fake() - - // We need an existing order before we can update its email, and send a receipt: - await sut.syncOrder(for: .init(purchasableItems: [makeItem()]), retryHandler: { }) - - // When - try await sut.sendReceipt(recipientEmail: "test@example.com") - - // Then - #expect(mockReceiptService.sendReceiptWasCalled == true) - #expect(mockReceiptService.spyIsEligibleForPOSReceipt == false) - } - @Test("Ineligible core plugin versions with feature flag enabled", arguments: Constants.ineligibleWCPluginVersions) - func sendReceipt_when_feature_flag_enabled_and_ineligible_plugin_version_sets_isEligibleForPOSReceipt_false(wcPluginVersion: String) async throws { + func sendReceipt_when_ineligible_plugin_version_sets_isEligibleForPOSReceipt_false(wcPluginVersion: String) async throws { // Given let mockReceiptService = MockReceiptService() - let mockFeatureFlagService = MockFeatureFlagService() let mockPluginsService = MockPluginsService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true mockPluginsService.setMockPlugin(.wooCommerce, systemPlugin: SystemPlugin.fake().copy(plugin: "woocommerce/woocommerce.php", version: wcPluginVersion, @@ -802,7 +747,6 @@ struct PointOfSaleOrderControllerTests { let sut = PointOfSaleOrderController(orderService: mockOrderService, receiptService: mockReceiptService, analytics: ServiceLocator.analytics, - featureFlagService: mockFeatureFlagService, pluginsService: mockPluginsService) mockOrderService.orderToReturn = Order.fake() @@ -817,23 +761,20 @@ struct PointOfSaleOrderControllerTests { #expect(mockReceiptService.spyIsEligibleForPOSReceipt == false) } - @Test("Unavailable core plugin with feature flag enabled", + @Test("Unavailable core plugin", arguments: [ SystemPlugin.fake().copy(plugin: "woocommerce/woocommerce.php", active: false), nil ]) - func sendReceipt_when_feature_flag_enabled_and_plugin_unavailable_sets_isEligibleForPOSReceipt_false(plugin: SystemPlugin?) async throws { + func sendReceipt_when_plugin_unavailable_sets_isEligibleForPOSReceipt_false(plugin: SystemPlugin?) async throws { // Given let mockReceiptService = MockReceiptService() - let mockFeatureFlagService = MockFeatureFlagService() let mockPluginsService = MockPluginsService() - mockFeatureFlagService.isFeatureFlagEnabledReturnValue[.pointOfSaleReceipts] = true mockPluginsService.setMockPlugin(.wooCommerce, systemPlugin: plugin) let sut = PointOfSaleOrderController(orderService: mockOrderService, receiptService: mockReceiptService, analytics: ServiceLocator.analytics, - featureFlagService: mockFeatureFlagService, pluginsService: mockPluginsService) mockOrderService.orderToReturn = Order.fake() From 08ece84a835cc970140011b8de0975fa6ced7f69 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 8 Sep 2025 21:21:22 +0700 Subject: [PATCH 2/2] remove DI flag service from pos order controller --- .../Classes/POS/Controllers/PointOfSaleOrderController.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift b/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift index e8cf5460c60..0058b950073 100644 --- a/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift +++ b/WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift @@ -1,6 +1,5 @@ import Foundation import Observation -import protocol Experiments.FeatureFlagService import protocol Yosemite.StoresManager import protocol Yosemite.POSOrderServiceProtocol import protocol Yosemite.POSReceiptServiceProtocol @@ -45,7 +44,6 @@ protocol PointOfSaleOrderControllerProtocol { stores: StoresManager = ServiceLocator.stores, currencySettings: CurrencySettings = ServiceLocator.currencySettings, analytics: Analytics = ServiceLocator.analytics, - featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService, pluginsService: PluginsServiceProtocol = PluginsService(storageManager: ServiceLocator.storageManager), celebration: PaymentCaptureCelebrationProtocol = PaymentCaptureCelebration()) { self.orderService = orderService @@ -54,7 +52,6 @@ protocol PointOfSaleOrderControllerProtocol { self.storeCurrency = currencySettings.currencyCode self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings) self.analytics = analytics - self.featureFlagService = featureFlagService self.pluginsService = pluginsService self.celebration = celebration } @@ -67,7 +64,6 @@ protocol PointOfSaleOrderControllerProtocol { private let storeCurrency: CurrencyCode private let analytics: Analytics private let stores: StoresManager - private let featureFlagService: FeatureFlagService private let pluginsService: PluginsServiceProtocol private(set) var orderState: PointOfSaleInternalOrderState = .idle