Skip to content

Commit 50bf66e

Browse files
committed
Create POSOrderMapper to set formatted and calculated totals on POSOrder
1 parent 45b67cd commit 50bf66e

File tree

8 files changed

+138
-74
lines changed

8 files changed

+138
-74
lines changed

Modules/Sources/Yosemite/PointOfSale/OrderList/POSOrder.swift

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,49 @@ public struct POSOrder: Equatable, Hashable {
1313
public let datePaid: Date?
1414
public let status: OrderStatusEnum
1515
public let total: String
16+
public let formattedTotal: String
17+
public let formattedSubtotal: String
1618
public let customerEmail: String?
1719
public let paymentMethodID: String
1820
public let paymentMethodTitle: String
1921
public let lineItems: [POSOrderItem]
2022
public let refunds: [POSOrderRefund]
2123
public let currency: String
2224
public let discountTotal: String
25+
public let formattedDiscountTotal: String?
2326
public let totalTax: String
27+
public let formattedTotalTax: String
28+
public let formattedPaymentTotal: String
29+
public let formattedNetAmount: String?
2430

2531
public init(id: Int64,
2632
number: String,
2733
dateCreated: Date,
2834
datePaid: Date? = nil,
2935
status: OrderStatusEnum,
3036
total: String,
37+
formattedTotal: String,
38+
formattedSubtotal: String,
3139
customerEmail: String? = nil,
3240
paymentMethodID: String,
3341
paymentMethodTitle: String,
3442
lineItems: [POSOrderItem] = [],
3543
refunds: [POSOrderRefund] = [],
3644
currency: String,
3745
discountTotal: String,
38-
totalTax: String) {
46+
totalTax: String,
47+
formattedTotalTax: String,
48+
formattedDiscountTotal: String?,
49+
formattedPaymentTotal: String,
50+
formattedNetAmount: String? = nil) {
3951
self.id = id
4052
self.number = number
4153
self.dateCreated = dateCreated
4254
self.datePaid = datePaid
4355
self.status = status
4456
self.total = total
57+
self.formattedTotal = formattedTotal
58+
self.formattedSubtotal = formattedSubtotal
4559
self.customerEmail = customerEmail
4660
self.paymentMethodID = paymentMethodID
4761
self.paymentMethodTitle = paymentMethodTitle
@@ -50,36 +64,9 @@ public struct POSOrder: Equatable, Hashable {
5064
self.currency = currency
5165
self.discountTotal = discountTotal
5266
self.totalTax = totalTax
53-
}
54-
}
55-
56-
// MARK: - Conversion from NetworkingCore.Order
57-
public extension POSOrder {
58-
init(from order: NetworkingCore.Order) {
59-
// Extract customer email from billing address
60-
let customerEmail = order.billingAddress?.email
61-
62-
// Convert line items to POS format
63-
let posLineItems = order.items.map { POSOrderItem(from: $0) }
64-
65-
// Convert refunds to POS format
66-
let posRefunds = order.refunds.map { POSOrderRefund(from: $0) }
67-
68-
self.init(
69-
id: order.orderID,
70-
number: order.number,
71-
dateCreated: order.dateCreated,
72-
datePaid: order.datePaid,
73-
status: order.status,
74-
total: order.total,
75-
customerEmail: customerEmail,
76-
paymentMethodID: order.paymentMethodID,
77-
paymentMethodTitle: order.paymentMethodTitle,
78-
lineItems: posLineItems,
79-
refunds: posRefunds,
80-
currency: order.currency,
81-
discountTotal: order.discountTotal,
82-
totalTax: order.totalTax
83-
)
67+
self.formattedTotalTax = formattedTotalTax
68+
self.formattedDiscountTotal = formattedDiscountTotal
69+
self.formattedPaymentTotal = formattedPaymentTotal
70+
self.formattedNetAmount = formattedNetAmount
8471
}
8572
}
Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import Foundation
2-
import struct NetworkingCore.OrderItem
3-
import struct NetworkingCore.OrderItemAttribute
42

53
public struct POSOrderItem: Equatable, Hashable {
64
public let itemID: Int64
@@ -9,8 +7,10 @@ public struct POSOrderItem: Equatable, Hashable {
97
public let variationID: Int64
108
public let quantity: Decimal
119
public let price: NSDecimalNumber
10+
public let formattedPrice: String
1211
public let subtotal: String
1312
public let total: String
13+
public let formattedTotal: String
1414
public let attributes: [OrderItemAttribute]
1515

1616
public init(itemID: Int64,
@@ -19,34 +19,21 @@ public struct POSOrderItem: Equatable, Hashable {
1919
variationID: Int64,
2020
quantity: Decimal,
2121
price: NSDecimalNumber,
22+
formattedPrice: String,
2223
subtotal: String,
2324
total: String,
25+
formattedTotal: String,
2426
attributes: [OrderItemAttribute]) {
2527
self.itemID = itemID
2628
self.name = name
2729
self.productID = productID
2830
self.variationID = variationID
2931
self.quantity = quantity
3032
self.price = price
33+
self.formattedPrice = formattedPrice
3134
self.subtotal = subtotal
3235
self.total = total
36+
self.formattedTotal = formattedTotal
3337
self.attributes = attributes
3438
}
3539
}
36-
37-
// MARK: - Conversion from NetworkingCore.OrderItem
38-
public extension POSOrderItem {
39-
init(from orderItem: OrderItem) {
40-
self.init(
41-
itemID: orderItem.itemID,
42-
name: orderItem.name,
43-
productID: orderItem.productID,
44-
variationID: orderItem.variationID,
45-
quantity: orderItem.quantity,
46-
price: orderItem.price,
47-
subtotal: orderItem.subtotal,
48-
total: orderItem.total,
49-
attributes: orderItem.attributes
50-
)
51-
}
52-
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import Foundation
2+
import class WooFoundationCore.CurrencyFormatter
3+
import struct NetworkingCore.Order
4+
import struct NetworkingCore.OrderItem
5+
import struct NetworkingCore.OrderItemAttribute
6+
import struct NetworkingCore.OrderRefundCondensed
7+
8+
struct POSOrderMapper {
9+
private let currencyFormatter: CurrencyFormatter
10+
11+
init(currencyFormatter: CurrencyFormatter) {
12+
self.currencyFormatter = currencyFormatter
13+
}
14+
15+
func map(order: NetworkingCore.Order) -> POSOrder {
16+
let customerEmail = order.billingAddress?.email
17+
18+
let posLineItems = order.items.map { map(orderItem: $0, currency: order.currency) }
19+
20+
let posRefunds = order.refunds.map { map(orderRefund: $0, currency: order.currency) }
21+
22+
let formattedDiscountTotal: String? = {
23+
guard let discountTotalValue = Double(order.discountTotal), discountTotalValue > 0 else {
24+
return nil
25+
}
26+
return currencyFormatter.formatAmount(order.discountTotal, with: order.currency, isNegative: true) ?? ""
27+
}()
28+
29+
return POSOrder(
30+
id: order.orderID,
31+
number: order.number,
32+
dateCreated: order.dateCreated,
33+
datePaid: order.datePaid,
34+
status: order.status,
35+
total: order.total,
36+
formattedTotal: currencyFormatter.formatAmount(order.total, with: order.currency) ?? "",
37+
formattedSubtotal: order.subtotalValue(currencyFormatter: currencyFormatter),
38+
customerEmail: customerEmail,
39+
paymentMethodID: order.paymentMethodID,
40+
paymentMethodTitle: order.paymentMethodTitle,
41+
lineItems: posLineItems,
42+
refunds: posRefunds,
43+
currency: order.currency,
44+
discountTotal: order.discountTotal,
45+
totalTax: order.totalTax,
46+
formattedTotalTax: currencyFormatter.formatAmount(order.totalTax, with: order.currency) ?? "",
47+
formattedDiscountTotal: formattedDiscountTotal,
48+
formattedPaymentTotal: order.paymentTotal(currencyFormatter: currencyFormatter),
49+
formattedNetAmount: order.netAmount(currencyFormatter: currencyFormatter)
50+
)
51+
}
52+
53+
private func map(orderItem: NetworkingCore.OrderItem, currency: String) -> POSOrderItem {
54+
return POSOrderItem(
55+
itemID: orderItem.itemID,
56+
name: orderItem.name,
57+
productID: orderItem.productID,
58+
variationID: orderItem.variationID,
59+
quantity: orderItem.quantity,
60+
price: orderItem.price,
61+
formattedPrice: currencyFormatter.formatAmount(orderItem.price, with: currency) ?? "",
62+
subtotal: orderItem.subtotal,
63+
total: orderItem.total,
64+
formattedTotal: currencyFormatter.formatAmount(orderItem.total, with: currency) ?? "",
65+
attributes: orderItem.attributes
66+
)
67+
}
68+
69+
private func map(orderRefund: NetworkingCore.OrderRefundCondensed, currency: String) -> POSOrderRefund {
70+
return POSOrderRefund(
71+
refundID: orderRefund.refundID,
72+
total: orderRefund.total,
73+
formattedTotal: currencyFormatter.formatAmount(orderRefund.total, with: currency) ?? "",
74+
reason: orderRefund.reason
75+
)
76+
}
77+
}
Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,20 @@
11
import Foundation
22
import struct NetworkingCore.OrderRefundCondensed
3+
import class WooFoundationCore.CurrencyFormatter
34

45
public struct POSOrderRefund: Equatable, Hashable {
56
public let refundID: Int64
67
public let total: String
8+
public let formattedTotal: String
79
public let reason: String?
810

911
public init(refundID: Int64,
1012
total: String,
13+
formattedTotal: String,
1114
reason: String? = nil) {
1215
self.refundID = refundID
1316
self.total = total
17+
self.formattedTotal = formattedTotal
1418
self.reason = reason
1519
}
1620
}
17-
18-
// MARK: - Conversion from NetworkingCore.OrderRefundCondensed
19-
public extension POSOrderRefund {
20-
init(from refund: OrderRefundCondensed) {
21-
self.init(
22-
refundID: refund.refundID,
23-
total: refund.total,
24-
reason: refund.reason
25-
)
26-
}
27-
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Foundation
22
import class Networking.AlamofireNetwork
33
import class Networking.OrdersRemote
4+
import class WooFoundationCore.CurrencyFormatter
45

56
public protocol PointOfSaleOrderListFetchStrategyFactoryProtocol {
67
func defaultStrategy() -> PointOfSaleOrderListFetchStrategy
@@ -9,16 +10,24 @@ public protocol PointOfSaleOrderListFetchStrategyFactoryProtocol {
910
public final class PointOfSaleOrderListFetchStrategyFactory: PointOfSaleOrderListFetchStrategyFactoryProtocol {
1011
private let siteID: Int64
1112
private let ordersRemote: OrdersRemote
13+
private let currencyFormatter: CurrencyFormatter
1214

1315
public init(siteID: Int64,
14-
credentials: Credentials?) {
16+
credentials: Credentials?,
17+
currencyFormatter: CurrencyFormatter) {
1518
self.siteID = siteID
1619
let network = AlamofireNetwork(credentials: credentials)
1720
self.ordersRemote = OrdersRemote(network: network)
21+
self.currencyFormatter = currencyFormatter
1822
}
1923

2024
public func defaultStrategy() -> PointOfSaleOrderListFetchStrategy {
21-
PointOfSaleDefaultOrderListFetchStrategy(orderListService: PointOfSaleOrderListService(siteID: siteID,
22-
ordersRemote: ordersRemote))
25+
PointOfSaleDefaultOrderListFetchStrategy(
26+
orderListService: PointOfSaleOrderListService(
27+
siteID: siteID,
28+
ordersRemote: ordersRemote,
29+
currencyFormatter: currencyFormatter
30+
)
31+
)
2332
}
2433
}

Modules/Sources/Yosemite/PointOfSale/OrderList/PointOfSaleOrderListService.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@ import enum Alamofire.AFError
33
import struct NetworkingCore.PagedItems
44
import struct NetworkingCore.Order
55
import protocol NetworkingCore.POSOrdersRemoteProtocol
6+
import class WooFoundationCore.CurrencyFormatter
67

78
public final class PointOfSaleOrderListService: PointOfSaleOrderListServiceProtocol {
89
private let ordersRemote: POSOrdersRemoteProtocol
910
private let siteID: Int64
11+
private let mapper: POSOrderMapper
1012

11-
public init(siteID: Int64, ordersRemote: POSOrdersRemoteProtocol) {
13+
public init(
14+
siteID: Int64,
15+
ordersRemote: POSOrdersRemoteProtocol,
16+
currencyFormatter: CurrencyFormatter
17+
) {
1218
self.siteID = siteID
1319
self.ordersRemote = ordersRemote
20+
self.mapper = POSOrderMapper(currencyFormatter: currencyFormatter)
1421
}
1522

1623
public func providePointOfSaleOrders(pageNumber: Int = 1) async throws -> PagedItems<POSOrder> {
@@ -26,7 +33,7 @@ public final class PointOfSaleOrderListService: PointOfSaleOrderListServiceProto
2633
}
2734

2835
// Convert Order objects to POSOrder objects
29-
let posOrders = pagedOrders.items.map { POSOrder(from: $0) }
36+
let posOrders = pagedOrders.items.map { mapper.map(order: $0) }
3037

3138
return .init(items: posOrders,
3239
hasMorePages: pagedOrders.hasMorePages,

WooCommerce/Classes/POS/Controllers/PointOfSaleOrderListController.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import struct Yosemite.POSOrderRefund
1010
import class Yosemite.Store
1111

1212
protocol PointOfSaleOrderListControllerProtocol {
13-
var ordersViewState: OrderListState { get }
13+
var ordersViewState: POSOrderListState { get }
1414
var selectedOrder: POSOrder? { get }
1515
func loadOrders() async
1616
func refreshOrders() async
@@ -19,14 +19,14 @@ protocol PointOfSaleOrderListControllerProtocol {
1919
}
2020

2121
@Observable final class PointOfSaleOrderListController: PointOfSaleOrderListControllerProtocol {
22-
var ordersViewState: OrderListState
22+
var ordersViewState: POSOrderListState
2323
private let paginationTracker: AsyncPaginationTracker
2424
private var fetchStrategy: PointOfSaleOrderListFetchStrategy
2525
private var cachedOrders: [POSOrder] = []
2626
private(set) var selectedOrder: POSOrder?
2727

2828
init(orderListFetchStrategyFactory: PointOfSaleOrderListFetchStrategyFactoryProtocol,
29-
initialState: OrderListState = .loading([])) {
29+
initialState: POSOrderListState = .loading([])) {
3030
self.ordersViewState = initialState
3131
self.paginationTracker = .init()
3232
self.fetchStrategy = orderListFetchStrategyFactory.defaultStrategy()
@@ -59,7 +59,7 @@ protocol PointOfSaleOrderListControllerProtocol {
5959
} catch {
6060
ordersViewState = .inlineError(currentOrders,
6161
error: .errorOnLoadingOrdersNextPage(error: error),
62-
context: OrderListState.InlineErrorContext.pagination)
62+
context: POSOrderListState.InlineErrorContext.pagination)
6363
}
6464
}
6565

@@ -77,7 +77,7 @@ protocol PointOfSaleOrderListControllerProtocol {
7777
} else {
7878
ordersViewState = .inlineError(orders,
7979
error: .errorOnLoadingOrders(error: error),
80-
context: OrderListState.InlineErrorContext.refresh)
80+
context: POSOrderListState.InlineErrorContext.refresh)
8181
}
8282
}
8383
}

WooCommerce/Classes/POS/TabBar/POSTabCoordinator.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Yosemite
55
import class WooFoundation.CurrencySettings
66
import protocol Storage.StorageManagerType
77
import protocol Storage.GRDBManagerProtocol
8+
import class WooFoundationCore.CurrencyFormatter
89

910
/// View controller that provides the tab bar item for the Point of Sale tab.
1011
/// It is never visible on the screen, only used to provide the tab bar item as all POS UI is full-screen.
@@ -126,8 +127,11 @@ private extension POSTabCoordinator {
126127
couponsSearchController: PointOfSaleCouponsController(itemProvider: posCouponProvider,
127128
fetchStrategyFactory: posCouponFetchStrategyFactory),
128129
ordersController: PointOfSaleOrderListController(
129-
orderListFetchStrategyFactory: PointOfSaleOrderListFetchStrategyFactory(siteID: siteID,
130-
credentials: credentials)
130+
orderListFetchStrategyFactory: PointOfSaleOrderListFetchStrategyFactory(
131+
siteID: siteID,
132+
credentials: credentials,
133+
currencyFormatter: CurrencyFormatter(currencySettings: currencySettings)
134+
)
131135
),
132136

133137
onPointOfSaleModeActiveStateChange: { [weak self] isEnabled in

0 commit comments

Comments
 (0)