Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
51e7e97
Add loadPOSOrders to OrdersRemote
staskus Aug 25, 2025
7b82d7e
Create PointOfSaleOrderService for providing orders on POS
staskus Aug 25, 2025
aa2642f
Create PointOfSaleOrdersController for managing loading, refresh, and…
staskus Aug 25, 2025
7057b9c
Add a simple in-memory cache for PointOfSaleOrdersController
staskus Aug 25, 2025
1dfec4a
Create POSOrder, POSOrderItem, POSOrderRefund to have separate POS mo…
staskus Aug 25, 2025
7ecdfb9
Create PointOfSaleOrderFetchStrategy
staskus Aug 25, 2025
53e56c3
Use common fields in OrdersRemote since Order model expects all the c…
staskus Aug 25, 2025
97d5d08
Inject PointOfSaleOrdersModel through entry point
staskus Aug 25, 2025
54e6f75
Create PointOfSaleOrdersModel for managing order list state
staskus Aug 25, 2025
ca2713f
Flatten OrderViewState
staskus Aug 25, 2025
b26a001
Update PointOfSaleOrdersControllerTests
staskus Aug 25, 2025
8738475
Create dummy UI for Order List and Details view for viewing loaded or…
staskus Aug 25, 2025
34c7e0c
Update PointOfSaleOrderFetchStrategy.swift
staskus Aug 26, 2025
b6545a5
Remove unused code
staskus Aug 26, 2025
c5c82eb
Merge branch 'trunk' into woomob-1131-woo-poshistorical-orders-orders…
staskus Aug 26, 2025
73434ab
Simplify new orders appending logic
staskus Aug 26, 2025
b8423db
Add a loading indicator to POSPageHeaderView
staskus Aug 26, 2025
acbb185
Display a small loading indicator when orders are cached but a new da…
staskus Aug 26, 2025
6f5e548
Rename PointOfSaleOrders to PointOfSaleOrderList
staskus Aug 27, 2025
7ff28cc
Merge branch 'trunk' into woomob-1131-woo-poshistorical-orders-orders…
staskus Aug 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Modules/Sources/NetworkingCore/Remote/OrdersRemote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,30 @@ extension OrdersRemote: POSOrdersRemoteProtocol {
}
}
}

public func loadPOSOrders(siteID: Int64, pageNumber: Int, pageSize: Int) async throws -> PagedItems<Order> {
let parameters: [String: Any] = [
ParameterKeys.page: String(pageNumber),
ParameterKeys.perPage: String(pageSize),
ParameterKeys.statusKey: Defaults.statusAny,
ParameterKeys.usesGMTDates: true,
ParameterKeys.fields: ParameterValues.fieldValues,
ParameterKeys.createdVia: "pos-rest-api"
]

let path = Constants.ordersPath
let request = JetpackRequest(wooApiVersion: .mark3,
method: .get,
siteID: siteID,
path: path,
parameters: parameters,
availableAsRESTRequest: true)
let mapper = OrderListMapper(siteID: siteID)

let orders: [Order] = try await enqueue(request, mapper: mapper)
let hasMorePages = orders.count == pageSize
return PagedItems(items: orders, hasMorePages: hasMorePages, totalItems: nil)
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ public protocol POSOrdersRemoteProtocol {
func createPOSOrder(siteID: Int64,
order: Order,
fields: [OrdersRemote.CreateOrderField]) async throws -> Order

func loadPOSOrders(siteID: Int64,
pageNumber: Int,
pageSize: Int) async throws -> PagedItems<Order>
}
73 changes: 73 additions & 0 deletions Modules/Sources/Yosemite/PointOfSale/OrderList/POSOrder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Foundation
import struct NetworkingCore.Address
import struct NetworkingCore.OrderItem
import struct NetworkingCore.OrderRefundCondensed
import struct NetworkingCore.MetaData
import enum NetworkingCore.OrderStatusEnum
import struct NetworkingCore.Order

public struct POSOrder: Equatable, Hashable {
public let id: Int64
public let number: String
public let dateCreated: Date
public let status: OrderStatusEnum
public let total: String
public let customerEmail: String?
public let paymentMethodTitle: String
public let lineItems: [POSOrderItem]
public let refunds: [POSOrderRefund]
public let currency: String
public let currencySymbol: String

public init(id: Int64,
number: String,
dateCreated: Date,
status: OrderStatusEnum,
total: String,
customerEmail: String? = nil,
paymentMethodTitle: String,
lineItems: [POSOrderItem] = [],
refunds: [POSOrderRefund] = [],
currency: String,
currencySymbol: String) {
self.id = id
self.number = number
self.dateCreated = dateCreated
self.status = status
self.total = total
self.customerEmail = customerEmail
self.paymentMethodTitle = paymentMethodTitle
self.lineItems = lineItems
self.refunds = refunds
self.currency = currency
self.currencySymbol = currencySymbol
}
}

// MARK: - Conversion from NetworkingCore.Order
public extension POSOrder {
init(from order: NetworkingCore.Order) {
// Extract customer email from billing address
let customerEmail = order.billingAddress?.email

// Convert line items to POS format
let posLineItems = order.items.map { POSOrderItem(from: $0) }

// Convert refunds to POS format
let posRefunds = order.refunds.map { POSOrderRefund(from: $0) }

self.init(
id: order.orderID,
number: order.number,
dateCreated: order.dateCreated,
status: order.status,
total: order.total,
customerEmail: customerEmail,
paymentMethodTitle: order.paymentMethodTitle,
lineItems: posLineItems,
refunds: posRefunds,
currency: order.currency,
currencySymbol: order.currencySymbol
)
}
}
31 changes: 31 additions & 0 deletions Modules/Sources/Yosemite/PointOfSale/OrderList/POSOrderItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation
import struct NetworkingCore.OrderItem

public struct POSOrderItem: Equatable, Hashable {
public let itemID: Int64
public let name: String
public let quantity: Decimal
public let total: String

public init(itemID: Int64,
name: String,
quantity: Decimal,
total: String) {
self.itemID = itemID
self.name = name
self.quantity = quantity
self.total = total
}
}

// MARK: - Conversion from NetworkingCore.OrderItem
public extension POSOrderItem {
init(from orderItem: OrderItem) {
self.init(
itemID: orderItem.itemID,
name: orderItem.name,
quantity: orderItem.quantity,
total: orderItem.total
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Foundation
import struct NetworkingCore.OrderRefundCondensed

public struct POSOrderRefund: Equatable, Hashable {
public let refundID: Int64
public let total: String
public let reason: String?

public init(refundID: Int64,
total: String,
reason: String? = nil) {
self.refundID = refundID
self.total = total
self.reason = reason
}
}

// MARK: - Conversion from NetworkingCore.OrderRefundCondensed
public extension POSOrderRefund {
init(from refund: OrderRefundCondensed) {
self.init(
refundID: refund.refundID,
total: refund.total,
reason: refund.reason
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation
import struct NetworkingCore.PagedItems

public protocol PointOfSaleOrderListFetchStrategy {
func fetchOrders(pageNumber: Int) async throws -> PagedItems<POSOrder>
}

struct PointOfSaleDefaultOrderListFetchStrategy: PointOfSaleOrderListFetchStrategy {
private let orderListService: PointOfSaleOrderListServiceProtocol

init(orderListService: PointOfSaleOrderListServiceProtocol) {
self.orderListService = orderListService
}

func fetchOrders(pageNumber: Int) async throws -> PagedItems<POSOrder> {
try await orderListService.providePointOfSaleOrders(pageNumber: pageNumber)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation
import class Networking.AlamofireNetwork
import class Networking.OrdersRemote

public protocol PointOfSaleOrderListFetchStrategyFactoryProtocol {
func defaultStrategy() -> PointOfSaleOrderListFetchStrategy
}

public final class PointOfSaleOrderListFetchStrategyFactory: PointOfSaleOrderListFetchStrategyFactoryProtocol {
private let siteID: Int64
private let ordersRemote: OrdersRemote

public init(siteID: Int64,
credentials: Credentials?) {
self.siteID = siteID
let network = AlamofireNetwork(credentials: credentials)
self.ordersRemote = OrdersRemote(network: network)
}

public func defaultStrategy() -> PointOfSaleOrderListFetchStrategy {
PointOfSaleDefaultOrderListFetchStrategy(orderListService: PointOfSaleOrderListService(siteID: siteID,
ordersRemote: ordersRemote))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Foundation
import enum Alamofire.AFError
import struct NetworkingCore.PagedItems
import struct NetworkingCore.Order
import protocol NetworkingCore.POSOrdersRemoteProtocol

public final class PointOfSaleOrderListService: PointOfSaleOrderListServiceProtocol {
private let ordersRemote: POSOrdersRemoteProtocol
private let siteID: Int64

public init(siteID: Int64, ordersRemote: POSOrdersRemoteProtocol) {
self.siteID = siteID
self.ordersRemote = ordersRemote
}

public func providePointOfSaleOrders(pageNumber: Int = 1) async throws -> PagedItems<POSOrder> {
do {
let pagedOrders = try await ordersRemote.loadPOSOrders(
siteID: siteID,
pageNumber: pageNumber,
pageSize: 25
)

if pageNumber != 1 && pagedOrders.items.count == 0 {
return .init(items: [], hasMorePages: false, totalItems: 0)
}

// Convert Order objects to POSOrder objects
let posOrders = pagedOrders.items.map { POSOrder(from: $0) }

return .init(items: posOrders,
hasMorePages: pagedOrders.hasMorePages,
totalItems: pagedOrders.totalItems)
} catch AFError.explicitlyCancelled {
throw PointOfSaleOrderListServiceError.requestCancelled
} catch {
throw PointOfSaleOrderListServiceError.requestFailed
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Foundation
import struct NetworkingCore.PagedItems

public enum PointOfSaleOrderListServiceError: Error, Equatable {
case requestFailed
case requestCancelled
}

public protocol PointOfSaleOrderListServiceProtocol {
func providePointOfSaleOrders(pageNumber: Int) async throws -> PagedItems<POSOrder>
}
20 changes: 20 additions & 0 deletions Modules/Tests/YosemiteTests/Mocks/MockPOSOrdersRemote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,24 @@ final class MockPOSOrdersRemote: POSOrdersRemoteProtocol {
spyCreatePOSOrderFields = fields
return Order.fake()
}

var mockPagedOrdersResult: Result<PagedItems<Order>, Error> = .success(PagedItems(items: [], hasMorePages: false, totalItems: 0))
var loadPOSOrdersCalled = false
var spySiteID: Int64?
var spyPageNumber: Int?
var spyPageSize: Int?

func loadPOSOrders(siteID: Int64, pageNumber: Int, pageSize: Int) async throws -> PagedItems<Order> {
loadPOSOrdersCalled = true
spySiteID = siteID
spyPageNumber = pageNumber
spyPageSize = pageSize

switch mockPagedOrdersResult {
case .success(let pagedOrders):
return pagedOrders
case .failure(let error):
throw error
}
}
}
Loading