Skip to content

Commit 65b643f

Browse files
authored
[Woo POS] Coupons: Sync from remote (#15423)
2 parents 1cfffc4 + 1a23559 commit 65b643f

File tree

4 files changed

+69
-14
lines changed

4 files changed

+69
-14
lines changed

Networking/Networking/Remote/CouponsRemote.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,23 @@ public final class CouponsRemote: Remote, CouponsRemoteProtocol {
372372
}
373373
}
374374

375+
extension CouponsRemote {
376+
public func loadAllCoupons(for siteID: Int64,
377+
pageNumber: Int = CouponsRemote.Default.pageNumber,
378+
pageSize: Int = CouponsRemote.Default.pageSize) async throws -> [Coupon] {
379+
try await withCheckedThrowingContinuation { continuation in
380+
loadAllCoupons(for: siteID, pageNumber: pageNumber, pageSize: pageSize) { result in
381+
switch result {
382+
case .success(let coupons):
383+
continuation.resume(returning: coupons)
384+
case .failure(let error):
385+
continuation.resume(throwing: error)
386+
}
387+
}
388+
}
389+
}
390+
}
391+
375392
// MARK: - Constants
376393
//
377394
public extension CouponsRemote {

WooCommerce/Classes/POS/Controllers/PointOfSaleCouponsController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Observation
22
import enum Yosemite.POSItem
3+
import enum Yosemite.CouponAction
34
import protocol Yosemite.PointOfSaleItemServiceProtocol
45

56
@available(iOS 17.0, *)

WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,12 @@ final class HubMenuViewModel: ObservableObject {
108108
private(set) lazy var posCouponProvider: PointOfSaleItemServiceProtocol = {
109109
let storage = ServiceLocator.storageManager
110110
let currencySettings = ServiceLocator.currencySettings
111+
let stores = ServiceLocator.stores
111112

112113
return PointOfSaleCouponService(siteID: siteID,
113114
currencySettings: currencySettings,
114115
credentials: credentials,
116+
stores: stores,
115117
storage: storage)
116118
}()
117119

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import protocol Networking.Network
22
import protocol Networking.ProductVariationsRemoteProtocol
3-
import class Networking.ProductsRemote
4-
import class Networking.ProductVariationsRemote
3+
import class Networking.CouponsRemote
54
import class Networking.AlamofireNetwork
65
import class WooFoundation.CurrencyFormatter
76
import class WooFoundation.CurrencySettings
@@ -10,52 +9,56 @@ import Storage
109
public final class PointOfSaleCouponService: PointOfSaleItemServiceProtocol {
1110
private var siteID: Int64
1211
private let currencyFormatter: CurrencyFormatter
13-
private let productsRemote: ProductsRemote
14-
private let variationRemote: ProductVariationsRemoteProtocol
12+
private let couponsRemote: CouponsRemote
13+
private let stores: StoresManager?
1514
private let storage: StorageManagerType?
1615

1716
public init(siteID: Int64,
1817
currencySettings: CurrencySettings,
1918
network: Network,
19+
stores: StoresManager? = nil,
2020
storage: StorageManagerType? = nil) {
2121
self.siteID = siteID
2222
self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings)
23-
self.productsRemote = ProductsRemote(network: network)
24-
self.variationRemote = ProductVariationsRemote(network: network)
23+
self.couponsRemote = CouponsRemote(network: network)
24+
self.stores = stores
2525
self.storage = storage
2626
}
2727

2828
public convenience init(siteID: Int64,
2929
currencySettings: CurrencySettings,
3030
credentials: Credentials?,
31+
stores: StoresManager,
3132
storage: StorageManagerType) {
3233
self.init(siteID: siteID,
3334
currencySettings: currencySettings,
3435
network: AlamofireNetwork(credentials: credentials),
36+
stores: stores,
3537
storage: storage)
3638
}
3739

3840
// TODO:
3941
// gh-15326 - Return PagedItems<POSItem> instead.
4042
@MainActor
41-
public func providePointOfSaleCoupons() -> [POSItem] {
43+
public func providePointOfSaleCoupons() async -> [POSItem] {
4244
guard let storage = storage else {
4345
return []
4446
}
47+
4548
let predicate = NSPredicate(format: "siteID == %lld", siteID)
4649
let descriptor = NSSortDescriptor(keyPath: \StorageCoupon.dateCreated,
4750
ascending: false)
4851

4952
let resultsController = ResultsController<StorageCoupon>(storageManager: storage,
50-
matching: predicate,
51-
sortedBy: [descriptor])
53+
matching: predicate,
54+
sortedBy: [descriptor])
5255

5356
do {
5457
try resultsController.performFetch()
55-
let storeCoupons = resultsController.fetchedObjects
56-
return mapCouponsToPOSItems(coupons: storeCoupons)
58+
let storageCoupons = resultsController.fetchedObjects
59+
return mapCouponsToPOSItems(coupons: storageCoupons)
5760
} catch {
58-
debugPrint(error)
61+
debugPrint("Failed to load coupons from storage:", error)
5962
return []
6063
}
6164
}
@@ -73,7 +76,39 @@ public final class PointOfSaleCouponService: PointOfSaleItemServiceProtocol {
7376

7477
@MainActor
7578
public func providePointOfSaleItems(pageNumber: Int) async throws -> PagedItems<POSItem> {
76-
let coupons = providePointOfSaleCoupons()
77-
return .init(items: coupons, hasMorePages: false)
79+
let coupons = await providePointOfSaleCoupons()
80+
81+
if !coupons.isEmpty {
82+
// Fire-and-forget sync
83+
Task.detached {
84+
await self.syncCouponsFromRemote(pageNumber: pageNumber)
85+
}
86+
return .init(items: coupons, hasMorePages: false)
87+
} else {
88+
// Wait for the sync to complete
89+
await syncCouponsFromRemote(pageNumber: pageNumber)
90+
let refreshedCoupons = await providePointOfSaleCoupons()
91+
return .init(items: refreshedCoupons, hasMorePages: false)
92+
}
93+
}
94+
95+
private func syncCouponsFromRemote(pageNumber: Int) async {
96+
guard let stores = stores else {
97+
return
98+
}
99+
100+
await withCheckedContinuation { continuation in
101+
let action = CouponAction.synchronizeCoupons(
102+
siteID: siteID,
103+
pageNumber: pageNumber,
104+
pageSize: 25,
105+
onCompletion: { _ in
106+
continuation.resume()
107+
}
108+
)
109+
Task { @MainActor in
110+
stores.dispatch(action)
111+
}
112+
}
78113
}
79114
}

0 commit comments

Comments
 (0)