Skip to content

Commit

Permalink
Merge pull request #43 from DatepollSystems/wr-377-duplicate-order-cr…
Browse files Browse the repository at this point in the history
…eation

WR-377: Prevent duplicate order creation on request timeout
  • Loading branch information
dev-Fabi authored Sep 17, 2024
2 parents 992ccee + 8c107fa commit 4471b43
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 4 deletions.
3 changes: 3 additions & 0 deletions shared/localization.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ order:
inputPlaceholder:
de: 1x ohne Tomaten
en: 1x without tomato
alreadyCreated:
en: Order was already sent.
de: Bestellung wurde bereits gesendet.
couldNotFindProduct:
title:
de: Produkt nicht gefunden.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.datepollsystems.waiterrobot.shared.utils

import java.util.UUID

actual fun randomUUID(): String = UUID.randomUUID().toString()
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ internal sealed class ApiException : Exception() {
@Serializable
@SerialName("STRIPE_DISABLED")
class StripeDisabled : ApiException()

@Serializable
@SerialName("ORDER_ALREADY_SUBMITTED")
class OrderAlreadySubmitted : ApiException()
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import org.datepollsystems.waiterrobot.shared.core.data.api.RequestBodyDto
@Serializable
class OrderRequestDto(
val tableId: Long,
val products: List<OrderItemDto>
val products: List<OrderItemDto>,
val clientOrderId: String,
) : RequestBodyDto {
@Serializable
class OrderItemDto(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import org.datepollsystems.waiterrobot.shared.features.table.models.Table

internal class OrderRepository(private val orderApi: OrderApi) : AbstractRepository() {

suspend fun sendOrder(table: Table, order: List<OrderItem>) {
suspend fun sendOrder(table: Table, order: List<OrderItem>, orderId: String) {
val items = order.map { OrderRequestDto.OrderItemDto(it.product.id, it.amount, it.note) }
orderApi.sendOrder(OrderRequestDto(table.id, items))
orderApi.sendOrder(OrderRequestDto(table.id, items, orderId))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.datepollsystems.waiterrobot.shared.generated.localization.L
import org.datepollsystems.waiterrobot.shared.generated.localization.desc
import org.datepollsystems.waiterrobot.shared.generated.localization.descOrderSent
import org.datepollsystems.waiterrobot.shared.utils.extensions.emptyToNull
import org.datepollsystems.waiterrobot.shared.utils.randomUUID
import org.orbitmvi.orbit.syntax.simple.SimpleContext
import org.orbitmvi.orbit.syntax.simple.SimpleSyntax
import org.orbitmvi.orbit.syntax.simple.intent
Expand All @@ -29,6 +30,8 @@ class OrderViewModel internal constructor(
private val initialItemId: Long?
) : AbstractViewModel<OrderState, OrderEffect>(OrderState()) {

private var currentOrderId = randomUUID()

override suspend fun SimpleSyntax<OrderState, NavOrViewModelEffect<OrderEffect>>.onCreate() {
coroutineScope {
launch { productRepository.listen() }
Expand Down Expand Up @@ -99,7 +102,8 @@ class OrderViewModel internal constructor(
}

try {
orderRepository.sendOrder(table, order)
orderRepository.sendOrder(table, order, currentOrderId)
currentOrderId = randomUUID()

reduce { state.copy(_currentOrder = Resource.Success(emptyMap())) }
navigator.popUpTo(Screen.TableDetailScreen(table), inclusive = false)
Expand All @@ -113,6 +117,10 @@ class OrderViewModel internal constructor(
} else {
reduce { stockToLow(stockToLowProduct, e.remaining) }
}
} catch (_: ApiException.OrderAlreadySubmitted) {
logger.w("Order was already submitted")
reduce { state.copy(_currentOrder = Resource.Success(emptyMap())) }
navigator.popUpTo(Screen.TableDetailScreen(table), inclusive = false)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.datepollsystems.waiterrobot.shared.core.data.api.ApiException
import org.datepollsystems.waiterrobot.shared.core.di.getLogger
import org.datepollsystems.waiterrobot.shared.generated.localization.L
import org.datepollsystems.waiterrobot.shared.generated.localization.accountNotActivated
import org.datepollsystems.waiterrobot.shared.generated.localization.alreadyCreated
import org.datepollsystems.waiterrobot.shared.generated.localization.amountToLow
import org.datepollsystems.waiterrobot.shared.generated.localization.desc
import org.datepollsystems.waiterrobot.shared.generated.localization.disabled
Expand Down Expand Up @@ -38,6 +39,7 @@ internal fun ApiException.getLocalizedUserMessage(): String = when (this) {
is ApiException.StripeDisabled -> L.stripeInit.error.disabled()
is ApiException.StripeNotActivated -> L.stripeInit.error.disabledForEvent()
is ApiException.ProductStockToLow -> L.order.stockToLow.title()
is ApiException.OrderAlreadySubmitted -> L.order.alreadyCreated()

// Unknown exceptions or exceptions that should normally not happen
is ApiException.Generic,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.datepollsystems.waiterrobot.shared.utils

expect fun randomUUID(): String
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.datepollsystems.waiterrobot.shared.utils

import platform.Foundation.NSUUID

actual fun randomUUID(): String = NSUUID().UUIDString

0 comments on commit 4471b43

Please sign in to comment.