Skip to content

Commit c5c82eb

Browse files
authored
Merge branch 'trunk' into woomob-1131-woo-poshistorical-orders-orders-fetching
2 parents b6545a5 + 46a5125 commit c5c82eb

File tree

10 files changed

+561
-46
lines changed

10 files changed

+561
-46
lines changed

Modules/Sources/Experiments/DefaultFeatureFlagService.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
100100
return true
101101
case .pointOfSaleHistoricalOrdersi1:
102102
return buildConfig == .localDeveloper || buildConfig == .alpha
103+
case .pointOfSaleLocalCatalogi1:
104+
return buildConfig == .localDeveloper || buildConfig == .alpha
103105
default:
104106
return true
105107
}

Modules/Sources/Experiments/FeatureFlag.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,9 @@ public enum FeatureFlag: Int {
206206
/// Enables the entry point for Point of Sale Orders
207207
///
208208
case pointOfSaleHistoricalOrdersi1
209+
210+
/// Enables Local Catalog i1 in Point of Sale.
211+
/// It syncs products and variations to local storage and display them in POS for quick access.
212+
///
213+
case pointOfSaleLocalCatalogi1
209214
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import Foundation
2+
3+
/// POS Catalog Sync: Remote Endpoints
4+
///
5+
public class POSCatalogSyncRemote: Remote {
6+
private let dateFormatter = ISO8601DateFormatter()
7+
8+
/// Loads POS products modified after the specified date.
9+
///
10+
/// - Parameters:
11+
/// - modifiedAfter: Only products modified after this date will be returned.
12+
/// - siteID: Site ID to load products from.
13+
/// - pageNumber: Page number for pagination.
14+
/// - Returns: Paginated list of POS products.
15+
///
16+
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
17+
public func loadProducts(modifiedAfter: Date, siteID: Int64, pageNumber: Int)
18+
async throws -> PagedItems<POSProduct> {
19+
let path = "products"
20+
let parameters = [
21+
ParameterKey.modifiedAfter: dateFormatter.string(from: modifiedAfter),
22+
ParameterKey.page: String(pageNumber),
23+
ParameterKey.perPage: String(Constants.defaultPageSize),
24+
ParameterKey.fields: POSProduct.requestFields.joined(separator: ",")
25+
]
26+
27+
let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: parameters)
28+
let mapper = ListMapper<POSProduct>(siteID: siteID)
29+
let (products, responseHeaders) = try await enqueueWithResponseHeaders(request, mapper: mapper)
30+
31+
return createPagedItems(items: products, responseHeaders: responseHeaders, currentPageNumber: pageNumber)
32+
}
33+
34+
/// Loads POS product variations modified after the specified date.
35+
///
36+
/// - Parameters:
37+
/// - modifiedAfter: Only variations modified after this date will be returned.
38+
/// - siteID: Site ID to load variations from.
39+
/// - pageNumber: Page number for pagination.
40+
/// - Returns: Paginated list of POS product variations.
41+
///
42+
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
43+
public func loadProductVariations(modifiedAfter: Date, siteID: Int64, pageNumber: Int) async throws -> PagedItems<POSProductVariation> {
44+
let path = "variations"
45+
let parameters = [
46+
ParameterKey.modifiedAfter: dateFormatter.string(from: modifiedAfter),
47+
ParameterKey.page: String(pageNumber),
48+
ParameterKey.perPage: String(Constants.defaultPageSize),
49+
ParameterKey.fields: POSProductVariation.requestFields.joined(separator: ",")
50+
]
51+
52+
let request = JetpackRequest(wooApiVersion: .wcAnalytics, method: .get, siteID: siteID, path: path, parameters: parameters)
53+
let mapper = ListMapper<POSProductVariation>(siteID: siteID)
54+
let (variations, responseHeaders) = try await enqueueWithResponseHeaders(request, mapper: mapper)
55+
56+
return createPagedItems(items: variations, responseHeaders: responseHeaders, currentPageNumber: pageNumber)
57+
}
58+
}
59+
60+
// MARK: - Constants
61+
//
62+
private extension POSCatalogSyncRemote {
63+
enum Constants {
64+
static let defaultPageSize = 100
65+
}
66+
67+
enum ParameterKey {
68+
static let modifiedAfter = "modified_after"
69+
static let page = "page"
70+
static let perPage = "per_page"
71+
static let fields = "_fields"
72+
}
73+
}

Modules/Sources/Networking/Remote/ProductVariationsRemote.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,7 @@ public class ProductVariationsRemote: Remote, ProductVariationsRemoteProtocol {
9797
let mapper = ListMapper<POSProductVariation>(siteID: siteID)
9898

9999
let (variations, responseHeaders) = try await enqueueWithResponseHeaders(request, mapper: mapper)
100-
101-
// Extracts the total number of pages from the response headers.
102-
// Response header names are case insensitive.
103-
let totalPages = responseHeaders?.first(where: { $0.key.lowercased() == Remote.PaginationHeaderKey.totalPagesCount.lowercased() })
104-
.flatMap { Int($0.value) }
105-
let hasMorePages = totalPages.map { pageNumber < $0 } ?? true
106-
107-
// Extract total count from X-WP-Total header
108-
let totalItems = responseHeaders?.first(where: { $0.key.lowercased() == Remote.PaginationHeaderKey.totalCount.lowercased() })
109-
.flatMap { Int($0.value) }
110-
111-
return PagedItems(items: variations, hasMorePages: hasMorePages, totalItems: totalItems)
100+
return createPagedItems(items: variations, responseHeaders: responseHeaders, currentPageNumber: pageNumber)
112101
}
113102

114103
private func productVariationsRequest(for siteID: Int64,

Modules/Sources/Networking/Remote/ProductsRemote.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -286,18 +286,7 @@ public final class ProductsRemote: Remote, ProductsRemoteProtocol {
286286
let mapper = ListMapper<POSProduct>(siteID: siteID)
287287

288288
let (products, responseHeaders) = try await enqueueWithResponseHeaders(request, mapper: mapper)
289-
290-
// Extracts the total number of pages from the response headers.
291-
// Response header names are case insensitive.
292-
let totalPages = responseHeaders?.first(where: { $0.key.lowercased() == Remote.PaginationHeaderKey.totalPagesCount.lowercased() })
293-
.flatMap { Int($0.value) }
294-
let hasMorePages = totalPages.map { pageNumber < $0 } ?? true
295-
296-
// Extract total count from X-WP-Total header
297-
let totalItems = responseHeaders?.first(where: { $0.key.lowercased() == Remote.PaginationHeaderKey.totalCount.lowercased() })
298-
.flatMap { Int($0.value) }
299-
300-
return .init(items: products, hasMorePages: hasMorePages, totalItems: totalItems)
289+
return createPagedItems(items: products, responseHeaders: responseHeaders, currentPageNumber: pageNumber)
301290
}
302291

303292
/// Remote search of products for the Point of Sale. Simple and variable products are loaded for WC version 9.6+, otherwise only simple products are loaded.

Modules/Sources/NetworkingCore/Remote/Remote.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,35 @@ public struct PagedItems<T> {
362362
}
363363
}
364364

365+
// MARK: - Pagination Helpers
366+
//
367+
public extension Remote {
368+
/// Creates a PagedItems instance from response data and headers.
369+
///
370+
/// - Parameters:
371+
/// - items: The parsed items from the response.
372+
/// - responseHeaders: HTTP response headers containing pagination info.
373+
/// - currentPageNumber: The current page number for determining if more pages exist.
374+
/// - Returns: PagedItems instance with pagination metadata.
375+
func createPagedItems<T>(items: [T],
376+
responseHeaders: [String: String]?,
377+
currentPageNumber: Int) -> PagedItems<T> {
378+
// Extract total pages from response headers (case insensitive)
379+
let totalPages = responseHeaders?.first(where: {
380+
$0.key.lowercased() == PaginationHeaderKey.totalPagesCount.lowercased()
381+
}).flatMap { Int($0.value) }
382+
383+
let hasMorePages = totalPages.map { currentPageNumber < $0 } ?? true
384+
385+
// Extract total count from response headers (case insensitive)
386+
let totalItems = responseHeaders?.first(where: {
387+
$0.key.lowercased() == PaginationHeaderKey.totalCount.lowercased()
388+
}).flatMap { Int($0.value) }
389+
390+
return PagedItems(items: items, hasMorePages: hasMorePages, totalItems: totalItems)
391+
}
392+
}
393+
365394
// MARK: - Constants!
366395
//
367396
public extension Remote {

0 commit comments

Comments
 (0)