Skip to content

Commit 8b6f4c3

Browse files
Woomob 1553 hide card reader for ciab sites (#16270)
2 parents 06e16dd + 49535da commit 8b6f4c3

File tree

10 files changed

+189
-63
lines changed

10 files changed

+189
-63
lines changed

Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
1-
21
import Foundation
2+
import protocol Storage.StorageManagerType
3+
import protocol NetworkingCore.Network
34

45
/// Determines whether an order is eligible for card present payment or not
56
///
67
public final class OrderCardPresentPaymentEligibilityStore: Store {
8+
private let currentSite: () -> Site?
9+
private lazy var siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol = CIABEligibilityChecker(
10+
currentSite: currentSite
11+
)
12+
13+
public init(
14+
dispatcher: Dispatcher,
15+
storageManager: StorageManagerType,
16+
network: Network,
17+
currentSite: @escaping () -> Site?
18+
) {
19+
self.currentSite = currentSite
20+
super.init(
21+
dispatcher: dispatcher,
22+
storageManager: storageManager,
23+
network: network
24+
)
25+
}
26+
727
/// Registers for supported Actions.
828
///
929
override public func registerSupportedActions(in dispatcher: Dispatcher) {
@@ -35,11 +55,27 @@ private extension OrderCardPresentPaymentEligibilityStore {
3555
cardPresentPaymentsConfiguration: CardPresentPaymentsConfiguration,
3656
onCompletion: (Result<Bool, Error>) -> Void) {
3757
let storage = storageManager.viewStorage
58+
59+
guard let site = storage.loadSite(siteID: siteID)?.toReadOnly() else {
60+
return onCompletion(
61+
.failure(
62+
OrderIsEligibleForCardPresentPaymentError.siteNotFoundInStorage
63+
)
64+
)
65+
}
66+
67+
guard siteCIABEligibilityChecker.isFeatureSupported(.cardReader, for: site) else {
68+
return onCompletion(
69+
.failure(
70+
OrderIsEligibleForCardPresentPaymentError.cardReaderPaymentOptionIsNotSupportedForCIABSites
71+
)
72+
)
73+
}
74+
3875
guard let order = storage.loadOrder(siteID: siteID, orderID: orderID)?.toReadOnly() else {
3976
return onCompletion(.failure(OrderIsEligibleForCardPresentPaymentError.orderNotFoundInStorage))
4077
}
4178

42-
4379
let orderProductsIDs = order.items.map(\.productID)
4480
let products = storage.loadProducts(siteID: siteID, productsIDs: orderProductsIDs).map { $0.toReadOnly() }
4581

@@ -50,5 +86,7 @@ private extension OrderCardPresentPaymentEligibilityStore {
5086
extension OrderCardPresentPaymentEligibilityStore {
5187
enum OrderIsEligibleForCardPresentPaymentError: Error {
5288
case orderNotFoundInStorage
89+
case siteNotFoundInStorage
90+
case cardReaderPaymentOptionIsNotSupportedForCIABSites
5391
}
5492
}

WooCommerce/Classes/CIAB/CIABAffectedFeature.swift renamed to Modules/Sources/Yosemite/Tools/CIAB/CIABAffectedFeature.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
/// Describes the feature set affected by CIAB sites
22
/// By the moment of introduction the features aren't supported by CIAB sites
33

4-
/// periphery: ignore:all - Used through `.allCases`
5-
enum CIABAffectedFeature: CaseIterable {
4+
public enum CIABAffectedFeature: CaseIterable {
65
case blaze
76
case payments
87
case splitShipments
98
case groupedProducts
109
case variableProducts
11-
case giftCardEditing
1210
case productsStockDashboardCard
1311
case pointOfSale
12+
case cardReader
1413
}
1514

1615
extension CIABAffectedFeature {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import Foundation
2+
3+
public final class CIABEligibilityChecker {
4+
public typealias ObtainSiteClosure = () -> Site?
5+
6+
public let currentSite: ObtainSiteClosure
7+
8+
public init(currentSite: @escaping ObtainSiteClosure) {
9+
self.currentSite = currentSite
10+
}
11+
}
12+
13+
extension CIABEligibilityChecker: CIABEligibilityCheckerProtocol {
14+
public var isCurrentSiteCIAB: Bool {
15+
guard let currentSite = currentSite() else {
16+
return false
17+
}
18+
return isSiteCIAB(currentSite)
19+
}
20+
21+
public func isSiteCIAB(_ site: Site) -> Bool {
22+
return site.isCIAB
23+
}
24+
25+
public func isFeatureSupportedForCurrentSite(_ feature: CIABAffectedFeature) -> Bool {
26+
return !isCurrentSiteCIAB || !CIABAffectedFeature.unsupportedFeatures.contains(feature)
27+
}
28+
29+
public func isFeatureSupported(
30+
_ feature: CIABAffectedFeature,
31+
for site: Site
32+
) -> Bool {
33+
return !isSiteCIAB(site) || !CIABAffectedFeature.unsupportedFeatures.contains(feature)
34+
}
35+
}
36+
37+
// MARK: - Site checks
38+
39+
private extension Site {
40+
var isCIAB: Bool {
41+
return isGarden && gardenName == GardenName.commerce.rawValue
42+
}
43+
}
44+
45+
private enum GardenName: String {
46+
/// Garden name for CIAB sites
47+
case commerce
48+
}

WooCommerce/Classes/CIAB/CIABEligibilityCheckerProtocol.swift renamed to Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityCheckerProtocol.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
2-
import Yosemite
32

4-
protocol CIABEligibilityCheckerProtocol {
3+
/// periphery: ignore
4+
public protocol CIABEligibilityCheckerProtocol {
55
var isCurrentSiteCIAB: Bool { get }
66

77
func isSiteCIAB(_ site: Site) -> Bool

Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,26 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase {
2727
///
2828
private var store: OrderCardPresentPaymentEligibilityStore!
2929

30+
private var currentSite: Site?
31+
3032
override func setUp() {
3133
super.setUp()
3234
dispatcher = Dispatcher()
3335
network = MockNetwork(useResponseQueue: true)
3436
storageManager = MockStorageManager()
35-
store = OrderCardPresentPaymentEligibilityStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
37+
store = OrderCardPresentPaymentEligibilityStore(
38+
dispatcher: dispatcher,
39+
storageManager: storageManager,
40+
network: network,
41+
currentSite: { [weak self] in
42+
return self?.currentSite
43+
}
44+
)
45+
}
46+
47+
override func tearDown() {
48+
currentSite = nil
49+
super.tearDown()
3650
}
3751

3852
// Other behavioural tests are in Order_CardPresentPaymentTests
@@ -55,6 +69,14 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase {
5569
name: "Chocolate cake",
5670
productTypeKey: "simple")
5771

72+
let regularSite = Site.fake().copy(
73+
siteID: sampleSiteID,
74+
isGarden: false,
75+
gardenName: nil
76+
)
77+
self.currentSite = regularSite
78+
79+
storageManager.insertSampleSite(readOnlySite: regularSite)
5880
storageManager.insertSampleProduct(readOnlyProduct: nonSubscriptionProduct)
5981
storageManager.insertSampleOrder(readOnlyOrder: cppEligibleOrder)
6082

@@ -75,4 +97,54 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase {
7597
let eligibility = try XCTUnwrap(result.get())
7698
XCTAssertTrue(eligibility)
7799
}
100+
101+
func test_orderIsEligibleForCardPresentPayment_returns_failure_for_CIAB_sites() throws {
102+
// Given
103+
let orderItem = OrderItem.fake().copy(itemID: 1234,
104+
name: "Chocolate cake",
105+
productID: 678,
106+
quantity: 1.0)
107+
let cppEligibleOrder = Order.fake().copy(siteID: sampleSiteID,
108+
orderID: 111,
109+
status: .pending,
110+
currency: "USD",
111+
datePaid: nil,
112+
total: "5.00",
113+
paymentMethodID: "woocommerce_payments",
114+
items: [orderItem])
115+
let nonSubscriptionProduct = Product.fake().copy(siteID: sampleSiteID,
116+
productID: 678,
117+
name: "Chocolate cake",
118+
productTypeKey: "simple")
119+
120+
let ciabSite = Site.fake().copy(
121+
siteID: sampleSiteID,
122+
isGarden: true,
123+
gardenName: "commerce"
124+
)
125+
self.currentSite = ciabSite
126+
127+
storageManager.insertSampleSite(readOnlySite: ciabSite)
128+
storageManager.insertSampleProduct(readOnlyProduct: nonSubscriptionProduct)
129+
storageManager.insertSampleOrder(readOnlyOrder: cppEligibleOrder)
130+
131+
let configuration = CardPresentPaymentsConfiguration(country: .US)
132+
133+
// When
134+
let result = waitFor { promise in
135+
let action = OrderCardPresentPaymentEligibilityAction
136+
.orderIsEligibleForCardPresentPayment(orderID: 111,
137+
siteID: self.sampleSiteID,
138+
cardPresentPaymentsConfiguration: configuration) { result in
139+
promise(result)
140+
}
141+
self.store.onAction(action)
142+
}
143+
144+
// Then
145+
XCTAssertThrowsError(try result.get()) { error in
146+
XCTAssertEqual(error as? OrderCardPresentPaymentEligibilityStore.OrderIsEligibleForCardPresentPaymentError,
147+
.cardReaderPaymentOptionIsNotSupportedForCIABSites)
148+
}
149+
}
78150
}
Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,12 @@
11
import Foundation
22
import Yosemite
33

4-
final class CIABEligibilityChecker {
5-
private let stores: StoresManager
6-
7-
init(stores: StoresManager = ServiceLocator.stores) {
8-
self.stores = stores
9-
}
10-
}
11-
12-
extension CIABEligibilityChecker: CIABEligibilityCheckerProtocol {
13-
var isCurrentSiteCIAB: Bool {
14-
guard let currentSite = stores.sessionManager.defaultSite else {
15-
return false
16-
}
17-
return isSiteCIAB(currentSite)
18-
}
19-
20-
func isSiteCIAB(_ site: Site) -> Bool {
21-
return site.isCIAB
22-
}
23-
24-
func isFeatureSupportedForCurrentSite(_ feature: CIABAffectedFeature) -> Bool {
25-
return !isCurrentSiteCIAB || !CIABAffectedFeature.unsupportedFeatures.contains(feature)
4+
extension CIABEligibilityChecker {
5+
convenience init() {
6+
self.init(
7+
currentSite: {
8+
return ServiceLocator.stores.sessionManager.defaultSite
9+
}
10+
)
2611
}
27-
28-
func isFeatureSupported(
29-
_ feature: CIABAffectedFeature,
30-
for site: Site
31-
) -> Bool {
32-
return !isSiteCIAB(site) || !CIABAffectedFeature.unsupportedFeatures.contains(feature)
33-
}
34-
}
35-
36-
// MARK: - Site checks
37-
38-
private extension Site {
39-
var isCIAB: Bool {
40-
return isGarden && gardenName == GardenName.commerce.rawValue
41-
}
42-
}
43-
44-
private enum GardenName: String {
45-
/// Garden name for CIAB sites
46-
case commerce
4712
}

WooCommerce/Classes/ViewRelated/Dashboard/Settings/POS/POSTabVisibilityChecker.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import protocol Yosemite.StoresManager
1111
import class Yosemite.POSEligibilityService
1212
import enum Yosemite.FeatureFlagAction
1313
import class Yosemite.SiteAddress
14+
import protocol Yosemite.CIABEligibilityCheckerProtocol
15+
import class Yosemite.CIABEligibilityChecker
1416
import enum Yosemite.POSCountryCurrencyValidator
1517

1618
final class POSTabVisibilityChecker: POSTabVisibilityCheckerProtocol {

WooCommerce/Classes/Yosemite/AuthenticatedState.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,14 @@ class AuthenticatedState: StoresManagerState {
7575
MediaStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
7676
NotificationStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
7777
NotificationCountStore(dispatcher: dispatcher, storageManager: storageManager, fileStorage: PListFileStorage()),
78-
OrderCardPresentPaymentEligibilityStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
78+
OrderCardPresentPaymentEligibilityStore(
79+
dispatcher: dispatcher,
80+
storageManager: storageManager,
81+
network: network,
82+
currentSite: {
83+
ServiceLocator.stores.sessionManager.defaultSite
84+
}
85+
),
7986
OrderNoteStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
8087
OrderStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
8188
OrderStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network),

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,9 +1013,7 @@
10131013
2DB8916B2E27F6D90001B175 /* OrderListCellViewModel+Localizations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB8916A2E27F6CE0001B175 /* OrderListCellViewModel+Localizations.swift */; };
10141014
2DB8916E2E27F7840001B175 /* OrderListCellViewModel+Localizations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB8916A2E27F6CE0001B175 /* OrderListCellViewModel+Localizations.swift */; };
10151015
2DCB54FA2E6AE8E100621F90 /* CIABEligibilityChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DCB54F92E6AE8D800621F90 /* CIABEligibilityChecker.swift */; };
1016-
2DCB54FC2E6AFE6A00621F90 /* CIABAffectedFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DCB54FB2E6AFE6900621F90 /* CIABAffectedFeature.swift */; };
10171016
2DE9DDFB2E6EF4A500155408 /* MockCIABEligibilityChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DE9DDFA2E6EF4A300155408 /* MockCIABEligibilityChecker.swift */; };
1018-
2DE9DDFD2E6EF53C00155408 /* CIABEligibilityCheckerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DE9DDFC2E6EF52E00155408 /* CIABEligibilityCheckerProtocol.swift */; };
10191017
2DF0D1BC2E2907C100F8995C /* MarkOrderAsReadUseCase+Woo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB88DA32E27DD790001B175 /* MarkOrderAsReadUseCase+Woo.swift */; };
10201018
310D1B482734919E001D55B4 /* InPersonPaymentsLiveSiteInTestModeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 310D1B472734919E001D55B4 /* InPersonPaymentsLiveSiteInTestModeView.swift */; };
10211019
311237EE2714DA240033C44E /* CardPresentModalDisplayMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 311237ED2714DA240033C44E /* CardPresentModalDisplayMessage.swift */; };
@@ -3897,9 +3895,7 @@
38973895
2DB891682E27F61C0001B175 /* OrderListCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderListCellViewModel.swift; sourceTree = "<group>"; };
38983896
2DB8916A2E27F6CE0001B175 /* OrderListCellViewModel+Localizations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OrderListCellViewModel+Localizations.swift"; sourceTree = "<group>"; };
38993897
2DCB54F92E6AE8D800621F90 /* CIABEligibilityChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIABEligibilityChecker.swift; sourceTree = "<group>"; };
3900-
2DCB54FB2E6AFE6900621F90 /* CIABAffectedFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIABAffectedFeature.swift; sourceTree = "<group>"; };
39013898
2DE9DDFA2E6EF4A300155408 /* MockCIABEligibilityChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCIABEligibilityChecker.swift; sourceTree = "<group>"; };
3902-
2DE9DDFC2E6EF52E00155408 /* CIABEligibilityCheckerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIABEligibilityCheckerProtocol.swift; sourceTree = "<group>"; };
39033899
310D1B472734919E001D55B4 /* InPersonPaymentsLiveSiteInTestModeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InPersonPaymentsLiveSiteInTestModeView.swift; sourceTree = "<group>"; };
39043900
311237ED2714DA240033C44E /* CardPresentModalDisplayMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentModalDisplayMessage.swift; sourceTree = "<group>"; };
39053901
311D21E7264AEDB900102316 /* CardPresentModalScanningForReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentModalScanningForReader.swift; sourceTree = "<group>"; };
@@ -7945,8 +7941,6 @@
79457941
2DCB54F82E6AE8C900621F90 /* CIAB */ = {
79467942
isa = PBXGroup;
79477943
children = (
7948-
2DE9DDFC2E6EF52E00155408 /* CIABEligibilityCheckerProtocol.swift */,
7949-
2DCB54FB2E6AFE6900621F90 /* CIABAffectedFeature.swift */,
79507944
2DCB54F92E6AE8D800621F90 /* CIABEligibilityChecker.swift */,
79517945
);
79527946
path = CIAB;
@@ -14166,7 +14160,6 @@
1416614160
CE7F778B2C074D2500C89F4E /* EditableOrderShippingLineViewModel.swift in Sources */,
1416714161
B95A45E92A77AE2C0073A91F /* CustomerSelectorViewModel.swift in Sources */,
1416814162
024DF3072372C18D006658FE /* AztecUIConfigurator.swift in Sources */,
14169-
2DCB54FC2E6AFE6A00621F90 /* CIABAffectedFeature.swift in Sources */,
1417014163
EE1B07F32C81CB4B006D9769 /* BlazeLocalNotificationScheduler.swift in Sources */,
1417114164
DE02ABBE2B578D0E008E0AC4 /* CreditCardType.swift in Sources */,
1417214165
020BE74823B05CF2007FE54C /* ProductInventoryEditableData.swift in Sources */,
@@ -14933,7 +14926,6 @@
1493314926
B626C71B287659D60083820C /* CustomFieldsListView.swift in Sources */,
1493414927
02ECD1E624FFB4E900735BE5 /* ProductFactory.swift in Sources */,
1493514928
260520F42B87BA23005D5D59 /* WooAnalyticsEvent+ConnectivityTool.swift in Sources */,
14936-
2DE9DDFD2E6EF53C00155408 /* CIABEligibilityCheckerProtocol.swift in Sources */,
1493714929
579CDEFF274D7E7900E8903D /* StoreStatsUsageTracksEventEmitter.swift in Sources */,
1493814930
CEDBDA472B6BEF2E002047D4 /* AnalyticsWebReport.swift in Sources */,
1493914931
314DC4BD268D158F00444C9E /* CardReaderSettingsKnownReadersProvider.swift in Sources */,

WooCommerce/WooCommerceTests/ViewRelated/CIAB/CIABEligibilityCheckerTests.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@ import XCTest
33
@testable import Yosemite
44

55
class CIABEligibilityCheckerTests: XCTestCase {
6-
private var storesManager: MockStoresManager!
76
private var sessionManager: SessionManager!
87
private var checker: CIABEligibilityChecker!
98

109
override func setUp() {
1110
super.setUp()
1211
sessionManager = .makeForTesting()
13-
storesManager = MockStoresManager(sessionManager: sessionManager)
14-
checker = CIABEligibilityChecker(stores: storesManager)
12+
checker = CIABEligibilityChecker(
13+
currentSite: {
14+
return MockStoresManager(
15+
sessionManager: self.sessionManager
16+
).sessionManager.defaultSite
17+
}
18+
)
1519
}
1620

1721
override func tearDown() {
1822
checker = nil
19-
storesManager = nil
2023
sessionManager = nil
2124
super.tearDown()
2225
}

0 commit comments

Comments
 (0)