Skip to content

Commit b5b60a5

Browse files
authored
Merge pull request #6168 from woocommerce/issue/6128-status-creation-support
Order Creation: Wire status support to LocalOrderSynchronizer
2 parents d5f6f0c + 6d3ffc9 commit b5b60a5

File tree

5 files changed

+38
-30
lines changed

5 files changed

+38
-30
lines changed

WooCommerce/Classes/ViewRelated/Orders/Order Creation/NewOrderViewModel.swift

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ final class NewOrderViewModel: ObservableObject {
134134
performingNetworkRequest
135135
}
136136

137+
/// Defines the current order status.
138+
///
139+
var currentOrderStatus: OrderStatusEnum {
140+
orderSynchronizer.order.status
141+
}
142+
137143
/// Representation of payment data display properties
138144
///
139145
@Published private(set) var paymentDataViewModel = PaymentDataViewModel()
@@ -142,6 +148,10 @@ final class NewOrderViewModel: ObservableObject {
142148
///
143149
private let analytics: Analytics
144150

151+
/// Order Synchronizer helper.
152+
///
153+
private let orderSynchronizer: OrderSynchronizer
154+
145155
init(siteID: Int64,
146156
stores: StoresManager = ServiceLocator.stores,
147157
storageManager: StorageManagerType = ServiceLocator.storageManager,
@@ -152,6 +162,7 @@ final class NewOrderViewModel: ObservableObject {
152162
self.storageManager = storageManager
153163
self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings)
154164
self.analytics = analytics
165+
self.orderSynchronizer = LocalOrderSynchronizer(siteID: siteID, stores: stores)
155166

156167
configureNavigationTrailingItem()
157168
configureStatusBadgeViewModel()
@@ -220,7 +231,7 @@ final class NewOrderViewModel: ObservableObject {
220231
func createOrder() {
221232
performingNetworkRequest = true
222233

223-
let action = OrderAction.createOrder(siteID: siteID, order: orderDetails.toOrder()) { [weak self] result in
234+
orderSynchronizer.commitAllChanges { [weak self] result in
224235
guard let self = self else { return }
225236
self.performingNetworkRequest = false
226237

@@ -234,7 +245,6 @@ final class NewOrderViewModel: ObservableObject {
234245
DDLogError("⛔️ Error creating new order: \(error)")
235246
}
236247
}
237-
stores.dispatch(action)
238248
trackCreateButtonTapped()
239249
}
240250

@@ -245,8 +255,8 @@ final class NewOrderViewModel: ObservableObject {
245255
/// Updates the order status & tracks its event
246256
///
247257
func updateOrderStatus(newStatus: OrderStatusEnum) {
248-
let oldStatus = orderDetails.status
249-
orderDetails.status = newStatus
258+
let oldStatus = orderSynchronizer.order.status
259+
orderSynchronizer.setStatus.send(newStatus)
250260
analytics.track(event: WooAnalyticsEvent.Orders.orderStatusChange(flow: .creation, orderID: nil, from: oldStatus, to: newStatus))
251261
}
252262
}
@@ -264,21 +274,15 @@ extension NewOrderViewModel {
264274
/// Type to hold all order detail values
265275
///
266276
struct OrderDetails {
267-
var status: OrderStatusEnum = .pending
268277
var items: [NewOrderItem] = []
269278
var billingAddress: Address?
270279
var shippingAddress: Address?
271280

272-
/// Used to create `Order` and check if order details have changed from empty/default values.
273-
/// Required because `Order` has `Date` properties that have to be the same to be Equatable.
274-
///
275-
let emptyOrder = Order.empty
276-
277281
func toOrder() -> Order {
278-
emptyOrder.copy(status: status,
279-
items: items.map { $0.orderItem },
280-
billingAddress: billingAddress,
281-
shippingAddress: shippingAddress)
282+
OrderFactory.emptyNewOrder.copy(status: .pending,
283+
items: items.map { $0.orderItem },
284+
billingAddress: billingAddress,
285+
shippingAddress: shippingAddress)
282286
}
283287
}
284288

@@ -403,13 +407,13 @@ private extension NewOrderViewModel {
403407
/// Calculates what navigation trailing item should be shown depending on our internal state.
404408
///
405409
func configureNavigationTrailingItem() {
406-
Publishers.CombineLatest($orderDetails, $performingNetworkRequest)
407-
.map { orderDetails, performingNetworkRequest -> NavigationItem in
410+
Publishers.CombineLatest(orderSynchronizer.orderPublisher, $performingNetworkRequest)
411+
.map { order, performingNetworkRequest -> NavigationItem in
408412
guard !performingNetworkRequest else {
409413
return .loading
410414
}
411415

412-
guard orderDetails.emptyOrder != orderDetails.toOrder() else {
416+
guard OrderFactory.emptyNewOrder != order else {
413417
return .none
414418
}
415419

@@ -421,10 +425,10 @@ private extension NewOrderViewModel {
421425
/// Updates status badge viewmodel based on status order property.
422426
///
423427
func configureStatusBadgeViewModel() {
424-
$orderDetails
425-
.map { [weak self] orderDetails in
426-
guard let siteOrderStatus = self?.currentSiteStatuses.first(where: { $0.status == orderDetails.status }) else {
427-
return StatusBadgeViewModel(orderStatusEnum: orderDetails.status)
428+
orderSynchronizer.orderPublisher
429+
.map { [weak self] order in
430+
guard let siteOrderStatus = self?.currentSiteStatuses.first(where: { $0.status == order.status }) else {
431+
return StatusBadgeViewModel(orderStatusEnum: order.status)
428432
}
429433
return StatusBadgeViewModel(orderStatus: siteOrderStatus)
430434
}
@@ -522,9 +526,9 @@ private extension NewOrderViewModel {
522526
/// or figure out a better way to get the product count.
523527
///
524528
func trackCreateButtonTapped() {
525-
let hasCustomerDetails = orderDetails.billingAddress != nil || orderDetails.shippingAddress != nil
526-
analytics.track(event: WooAnalyticsEvent.Orders.orderCreateButtonTapped(status: orderDetails.status,
527-
productCount: orderDetails.items.count,
529+
let hasCustomerDetails = orderSynchronizer.order.billingAddress != nil || orderSynchronizer.order.shippingAddress != nil
530+
analytics.track(event: WooAnalyticsEvent.Orders.orderCreateButtonTapped(status: orderSynchronizer.order.status,
531+
productCount: orderSynchronizer.order.items.count,
528532
hasCustomerDetails: hasCustomerDetails))
529533
}
530534

WooCommerce/Classes/ViewRelated/Orders/Order Creation/StatusSection/OrderStatusSection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct OrderStatusSection: View {
3434
.padding(.trailing, -Layout.linkButtonTrailingPadding) // remove trailing padding to align button title to the side
3535
.accessibilityLabel(Text(Localization.editButtonAccessibilityLabel))
3636
.sheet(isPresented: $viewModel.shouldShowOrderStatusList) {
37-
OrderStatusList(siteID: viewModel.siteID, status: viewModel.orderDetails.status) { newStatus in
37+
OrderStatusList(siteID: viewModel.siteID, status: viewModel.currentOrderStatus) { newStatus in
3838
viewModel.updateOrderStatus(newStatus: newStatus)
3939
}
4040
}

WooCommerce/Classes/ViewRelated/Orders/Order Creation/Synchronizer/LocalOrderSynchronizer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class LocalOrderSynchronizer: OrderSynchronizer {
1414
$state
1515
}
1616

17-
@Published private(set) var order: Order = Order.empty
17+
@Published private(set) var order: Order = OrderFactory.emptyNewOrder
1818

1919
var orderPublisher: Published<Order>.Publisher {
2020
$order

WooCommerce/WooCommerceTests/ViewRelated/Orders/Order Creation/NewOrderViewModelTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class NewOrderViewModelTests: XCTestCase {
2626
let viewModel = NewOrderViewModel(siteID: sampleSiteID)
2727

2828
// When
29-
viewModel.orderDetails.status = .processing
29+
viewModel.updateOrderStatus(newStatus: .processing)
3030

3131
// Then
3232
XCTAssertEqual(viewModel.navigationTrailingItem, .create)
@@ -82,7 +82,7 @@ class NewOrderViewModelTests: XCTestCase {
8282
let viewModel = NewOrderViewModel(siteID: sampleSiteID, stores: stores)
8383

8484
// When
85-
viewModel.orderDetails.status = .processing
85+
viewModel.updateOrderStatus(newStatus: .processing)
8686
stores.whenReceivingAction(ofType: OrderAction.self) { action in
8787
switch action {
8888
case let .createOrder(_, order, onCompletion):
@@ -144,7 +144,7 @@ class NewOrderViewModelTests: XCTestCase {
144144
XCTAssertEqual(viewModel.statusBadgeViewModel.title, "Pending payment")
145145

146146
// When
147-
viewModel.orderDetails.status = .processing
147+
viewModel.updateOrderStatus(newStatus: .processing)
148148

149149
// Then
150150
XCTAssertEqual(viewModel.statusBadgeViewModel.title, "Processing")

Yosemite/Yosemite/Stores/Order/OrderFactory.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Networking
33

44
/// Factory to create convenience order types.
55
///
6-
enum OrderFactory {
6+
public enum OrderFactory {
77
/// Creates an order suitable to be used as a simple payments order.
88
/// Under the hood it uses a fee line with or without taxes to create an order with the desired amount.
99
///
@@ -51,4 +51,8 @@ enum OrderFactory {
5151
taxes: [],
5252
attributes: [])
5353
}
54+
55+
/// References a new empty order with constants `Date` values.
56+
///
57+
public static let emptyNewOrder = Order.empty
5458
}

0 commit comments

Comments
 (0)