Skip to content
This repository was archived by the owner on Feb 4, 2025. It is now read-only.

Commit 1d688f2

Browse files
author
Anirudh Bhat
authored
Merge pull request #3054 from wordpress-mobile/issue/woo-11148-update-cash-payment-method
Update WCOrderStore to support updating payment method
2 parents e11c311 + c1f6ab2 commit 1d688f2

File tree

5 files changed

+185
-23
lines changed

5 files changed

+185
-23
lines changed

example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_WCOrdersTest.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,16 +217,18 @@ class MockedStack_WCOrdersTest : MockedStack_Base() {
217217
}
218218

219219
@Test
220-
fun testOrderStatusUpdateSuccess() = runBlocking {
220+
fun testOrderStatusAndPaymentMethodUpdateSuccess() = runBlocking {
221221
val originalOrder = OrderEntity(
222222
localSiteId = siteModel.localId(),
223223
status = CoreOrderStatus.PROCESSING.value,
224224
orderId = 88,
225-
total = "15.00"
225+
total = "15.00",
226+
paymentMethod = "cheque",
227+
paymentMethodTitle = "Check payments"
226228
)
227229

228230
interceptor.respondWith("wc-order-update-response-success.json")
229-
val payload = orderRestClient.updateOrderStatus(
231+
val payload = orderRestClient.updateOrderStatusAndPaymentMethod(
230232
originalOrder, siteModel, CoreOrderStatus.REFUNDED.value
231233
)
232234

@@ -235,11 +237,13 @@ class MockedStack_WCOrdersTest : MockedStack_Base() {
235237
assertEquals(siteModel.id, order.localSiteId.value)
236238
assertEquals(originalOrder.orderId, order.orderId)
237239
assertEquals(CoreOrderStatus.REFUNDED.value, order.status)
240+
assertEquals(originalOrder.paymentMethod, order.paymentMethod)
241+
assertEquals(originalOrder.paymentMethodTitle, order.paymentMethodTitle)
238242
}
239243
}
240244

241245
@Test
242-
fun testOrderStatusUpdateError() = runBlocking {
246+
fun testOrderStatusAndPaymentMethodUpdateError() = runBlocking {
243247
val originalOrder = OrderEntity(
244248
localSiteId = siteModel.localId(),
245249
status = CoreOrderStatus.PROCESSING.value,
@@ -253,7 +257,7 @@ class MockedStack_WCOrdersTest : MockedStack_Base() {
253257
}
254258

255259
interceptor.respondWithError(errorJson, 400)
256-
val payload = orderRestClient.updateOrderStatus(
260+
val payload = orderRestClient.updateOrderStatusAndPaymentMethod(
257261
originalOrder, siteModel, CoreOrderStatus.REFUNDED.value
258262
)
259263

example/src/test/java/org/wordpress/android/fluxc/wc/order/OrderTestUtils.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ object OrderTestUtils {
3232
orderId: Long,
3333
orderStatus: String = CoreOrderStatus.PROCESSING.value,
3434
siteId: Int = 6,
35-
modified: String = "1955-11-05T14:15:00Z"
35+
modified: String = "1955-11-05T14:15:00Z",
36+
paymentMethod: String = "",
37+
paymentMethodTitle: String = ""
3638
): OrderEntity {
3739
return OrderEntity(
3840
orderId = orderId,
@@ -42,7 +44,9 @@ object OrderTestUtils {
4244
dateCreated = "1955-11-05T14:15:00Z",
4345
datePaid = "1956-11-05T14:15:00Z",
4446
currency = "USD",
45-
total = "10.0"
47+
total = "10.0",
48+
paymentMethod = paymentMethod,
49+
paymentMethodTitle = paymentMethodTitle,
4650
)
4751
}
4852

example/src/test/java/org/wordpress/android/fluxc/wc/order/WCOrderStoreTest.kt

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ import kotlin.test.assertEquals
5959
import kotlin.test.assertNull
6060
import kotlin.test.assertTrue
6161

62+
private const val COD_PAYMENT_METHOD_ID = "cod"
63+
private const val CUSTOM_PAYMENT_METHOD_TITLE = "Pay in Person"
64+
65+
6266
@InternalCoroutinesApi
6367
@Config(manifest = Config.NONE)
6468
@RunWith(RobolectricTestRunner::class)
@@ -194,8 +198,9 @@ class WCOrderStoreTest {
194198
ordersDaoDecorator.insertOrUpdateOrder(orderModel)
195199
val site = SiteModel().apply { id = orderModel.localSiteId.value }
196200
val result = RemoteOrderPayload.Updating(orderModel.copy(status = CoreOrderStatus.REFUNDED.value), site)
197-
whenever(orderRestClient.updateOrderStatus(orderModel, site, CoreOrderStatus.REFUNDED.value))
198-
.thenReturn(result)
201+
whenever(orderRestClient
202+
.updateOrderStatusAndPaymentMethod(orderModel, site, CoreOrderStatus.REFUNDED.value)
203+
).thenReturn(result)
199204

200205
orderStore.updateOrderStatus(orderModel.orderId, site, WCOrderStatusModel(CoreOrderStatus.REFUNDED.value))
201206
.toList()
@@ -325,7 +330,7 @@ class WCOrderStoreTest {
325330
.saveToDb()
326331
val site = SiteModel().apply { id = orderModel.localSiteId.value }
327332
val result = RemoteOrderPayload.Updating(orderModel.copy(status = CoreOrderStatus.COMPLETED.value), site)
328-
whenever(orderRestClient.updateOrderStatus(orderModel, site, CoreOrderStatus.COMPLETED.value))
333+
whenever(orderRestClient.updateOrderStatusAndPaymentMethod(orderModel, site, CoreOrderStatus.COMPLETED.value))
329334
.thenReturn(result)
330335

331336
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.status)
@@ -348,7 +353,15 @@ class WCOrderStoreTest {
348353
.saveToDb()
349354
val site = SiteModel().apply { id = orderModel.localSiteId.value }
350355
val error = OrderError()
351-
whenever(orderRestClient.updateOrderStatus(any(), any(), any())).thenReturn(
356+
whenever(
357+
orderRestClient.updateOrderStatusAndPaymentMethod(
358+
any(),
359+
any(),
360+
any(),
361+
anyOrNull(),
362+
anyOrNull()
363+
)
364+
).thenReturn(
352365
RemoteOrderPayload.Updating(
353366
error = error,
354367
order = orderModel,
@@ -370,6 +383,106 @@ class WCOrderStoreTest {
370383
Unit
371384
}
372385

386+
387+
@Test
388+
fun testUpdateOrderPaymentMethodRequestUpdatesLocalDatabase() = runBlocking {
389+
val orderModel = OrderTestUtils.generateSampleOrder(
390+
42,
391+
orderStatus = CoreOrderStatus.PROCESSING.value,
392+
paymentMethod = "",
393+
paymentMethodTitle = "")
394+
.saveToDb()
395+
val site = SiteModel().apply { id = orderModel.localSiteId.value }
396+
whenever(orderRestClient.updateOrderStatusAndPaymentMethod(
397+
orderModel,
398+
site,
399+
CoreOrderStatus.COMPLETED.value,
400+
COD_PAYMENT_METHOD_ID,
401+
CUSTOM_PAYMENT_METHOD_TITLE
402+
)).thenReturn(
403+
RemoteOrderPayload.Updating(
404+
orderModel.copy(
405+
status = CoreOrderStatus.COMPLETED.value,
406+
paymentMethod = COD_PAYMENT_METHOD_ID,
407+
paymentMethodTitle = CUSTOM_PAYMENT_METHOD_TITLE
408+
),
409+
site
410+
)
411+
)
412+
413+
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethod)
414+
.isEqualTo("")
415+
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethodTitle)
416+
.isEqualTo("")
417+
418+
orderStore.updateOrderStatusAndPaymentMethod(
419+
orderModel.orderId,
420+
site,
421+
WCOrderStatusModel(CoreOrderStatus.COMPLETED.value),
422+
newPaymentMethodId = COD_PAYMENT_METHOD_ID,
423+
newPaymentMethodTitle = CUSTOM_PAYMENT_METHOD_TITLE
424+
).toList()
425+
426+
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethod)
427+
.isEqualTo(COD_PAYMENT_METHOD_ID)
428+
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethodTitle)
429+
.isEqualTo(CUSTOM_PAYMENT_METHOD_TITLE)
430+
Unit
431+
}
432+
433+
@Test
434+
fun testRevertLocalPaymentMethodIfRemoteUpdateFails() = runBlocking {
435+
val orderModel = OrderTestUtils.generateSampleOrder(
436+
42,
437+
orderStatus = CoreOrderStatus.PROCESSING.value,
438+
paymentMethod = "",
439+
paymentMethodTitle = "")
440+
.saveToDb()
441+
val site = SiteModel().apply { id = orderModel.localSiteId.value }
442+
val error = OrderError()
443+
whenever(
444+
orderRestClient.updateOrderStatusAndPaymentMethod(
445+
orderModel,
446+
site,
447+
CoreOrderStatus.COMPLETED.value,
448+
COD_PAYMENT_METHOD_ID,
449+
CUSTOM_PAYMENT_METHOD_TITLE
450+
)
451+
).thenReturn(
452+
RemoteOrderPayload.Updating(
453+
error = error,
454+
order = orderModel,
455+
site = site
456+
)
457+
)
458+
459+
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethod)
460+
.isEqualTo("")
461+
assertThat(ordersDaoDecorator.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethodTitle)
462+
.isEqualTo("")
463+
464+
val response = orderStore.updateOrderStatusAndPaymentMethod(
465+
orderModel.orderId,
466+
site,
467+
WCOrderStatusModel(CoreOrderStatus.COMPLETED.value),
468+
newPaymentMethodId = COD_PAYMENT_METHOD_ID,
469+
newPaymentMethodTitle = CUSTOM_PAYMENT_METHOD_TITLE
470+
).toList().last()
471+
472+
// Ensure the error is sent in the response
473+
assertThat(response.event.error).isEqualTo(error)
474+
475+
assertThat(
476+
ordersDaoDecorator
477+
.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethod
478+
).isEqualTo("")
479+
assertThat(
480+
ordersDaoDecorator
481+
.getOrder(orderModel.orderId, orderModel.localSiteId)?.paymentMethodTitle
482+
).isEqualTo("")
483+
Unit
484+
}
485+
373486
@Test
374487
fun testObserveOrdersCount() {
375488
runBlocking {

plugins/woocommerce/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/order/OrderRestClient.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,23 @@ class OrderRestClient @Inject constructor(
589589
}
590590
}
591591

592-
suspend fun updateOrderStatus(orderToUpdate: OrderEntity, site: SiteModel, status: String) =
593-
updateOrder(orderToUpdate, site, mapOf("status" to status))
592+
suspend fun updateOrderStatusAndPaymentMethod(
593+
orderToUpdate: OrderEntity,
594+
site: SiteModel,
595+
status: String,
596+
paymentMethodId: String? = null,
597+
paymentMethodTitle: String? = null,
598+
): RemoteOrderPayload.Updating {
599+
val updatePayload = mutableMapOf<String, Any>()
600+
updatePayload["status"] = status
601+
paymentMethodId?.let {
602+
updatePayload["payment_method"] = paymentMethodId
603+
}
604+
paymentMethodTitle?.let {
605+
updatePayload["payment_method_title"] = paymentMethodTitle
606+
}
607+
return updateOrder(orderToUpdate, site, updatePayload)
608+
}
594609

595610
suspend fun updateCustomerOrderNote(
596611
orderToUpdate: OrderEntity,

plugins/woocommerce/src/main/kotlin/org/wordpress/android/fluxc/store/WCOrderStore.kt

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -632,15 +632,26 @@ class WCOrderStore @Inject constructor(
632632
orderId: Long,
633633
site: SiteModel,
634634
newStatus: WCOrderStatusModel
635+
): Flow<UpdateOrderResult> =
636+
updateOrderStatusAndPaymentMethod(orderId, site, newStatus, null, null)
637+
638+
suspend fun updateOrderStatusAndPaymentMethod(
639+
orderId: Long,
640+
site: SiteModel,
641+
newStatus: WCOrderStatusModel,
642+
newPaymentMethodId: String?,
643+
newPaymentMethodTitle: String?,
635644
): Flow<UpdateOrderResult> {
636-
return coroutineEngine.flowWithDefaultContext(API, this, "updateOrderStatus") {
645+
return coroutineEngine.flowWithDefaultContext(API, this, "updateOrderStatusAndPaymentMethod") {
637646
val orderModel = ordersDaoDecorator.getOrder(orderId, site.localId())
638647

639648
if (orderModel != null) {
640-
updateOrderStatusLocally(
649+
optimisticallyUpdateOrder(
641650
orderId,
642651
site.localId(),
643652
newStatus.statusKey,
653+
newPaymentMethodId,
654+
newPaymentMethodTitle,
644655
OrdersDaoDecorator.ListUpdateStrategy.INVALIDATE
645656
)
646657

@@ -653,9 +664,15 @@ class WCOrderStore @Inject constructor(
653664
// Ensure the code gets executed even when the VM dies - eg. when the client app marks an order as
654665
// completed and navigates to a different screen.
655666
val remoteUpdateResult: OnOrderChanged = withContext(NonCancellable) {
656-
val remotePayload = wcOrderRestClient.updateOrderStatus(orderModel, site, newStatus.statusKey)
667+
val remotePayload = wcOrderRestClient.updateOrderStatusAndPaymentMethod(
668+
orderModel,
669+
site,
670+
newStatus.statusKey,
671+
newPaymentMethodId,
672+
newPaymentMethodTitle,
673+
)
657674
if (remotePayload.isError) {
658-
revertOrderStatus(remotePayload)
675+
revertOptimisticOrderUpdate(remotePayload)
659676
} else {
660677
ordersDaoDecorator.insertOrUpdateOrder(
661678
remotePayload.order,
@@ -697,14 +714,21 @@ class WCOrderStore @Inject constructor(
697714
forceNew
698715
)
699716

700-
private suspend fun updateOrderStatusLocally(
717+
private suspend fun optimisticallyUpdateOrder(
701718
orderId: Long,
702719
localSiteId: LocalId,
703720
newStatus: String,
721+
newPaymentMethodId: String? = null,
722+
newPaymentMethodTitle: String? = null,
704723
listUpdateStrategy: OrdersDaoDecorator.ListUpdateStrategy = OrdersDaoDecorator.ListUpdateStrategy.DEFAULT
705724
) {
706-
val updatedOrder = ordersDaoDecorator.getOrder(orderId, localSiteId)!!
707-
.copy(status = newStatus)
725+
val updatedOrder = ordersDaoDecorator.getOrder(orderId, localSiteId)!!.let {
726+
it.copy(
727+
status = newStatus,
728+
paymentMethod = newPaymentMethodId ?: it.paymentMethod,
729+
paymentMethodTitle = newPaymentMethodTitle ?: it.paymentMethodTitle
730+
)
731+
}
708732
ordersDaoDecorator.insertOrUpdateOrder(updatedOrder, listUpdateStrategy)
709733
}
710734

@@ -992,11 +1016,13 @@ class WCOrderStore @Inject constructor(
9921016
emitChange(onOrderChanged)
9931017
}
9941018

995-
private suspend fun revertOrderStatus(payload: RemoteOrderPayload.Updating): OnOrderChanged {
996-
updateOrderStatusLocally(
1019+
private suspend fun revertOptimisticOrderUpdate(payload: RemoteOrderPayload.Updating): OnOrderChanged {
1020+
optimisticallyUpdateOrder(
9971021
payload.order.orderId,
9981022
payload.order.localSiteId,
999-
payload.order.status
1023+
payload.order.status,
1024+
payload.order.paymentMethod,
1025+
payload.order.paymentMethodTitle
10001026
)
10011027
return OnOrderChanged(orderError = payload.error)
10021028
}

0 commit comments

Comments
 (0)