Skip to content

Commit

Permalink
Unfinished item update from SynQ
Browse files Browse the repository at this point in the history
  • Loading branch information
anotheroneofthese committed Oct 4, 2024
1 parent 3989646 commit 2ed3ffc
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,4 @@ class SecurityConfig {
@Bean
@Order(Ordered.LOWEST_PRECEDENCE)
fun jwtDecoder(): JwtDecoder = JwtDecoders.fromIssuerLocation(issuerUri)

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,4 @@ class SecurityConfig {
@Bean("synqJwtDecoder")
@Order(Ordered.HIGHEST_PRECEDENCE)
fun jwtDecoder(): JwtDecoder = JwtDecoders.fromIssuerLocation(issuerUri)

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import io.swagger.v3.oas.models.info.Contact
import io.swagger.v3.oas.models.info.Info
import io.swagger.v3.oas.models.security.SecurityRequirement
import org.springdoc.core.models.GroupedOpenApi
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package no.nb.mlt.wls.application.synqapi.synq

import io.swagger.v3.oas.annotations.media.Schema
import no.nb.mlt.wls.domain.model.HostName
import no.nb.mlt.wls.domain.ports.inbound.MoveItemPayload

@Schema(
description = "Payload for receiving Item updates in batch from SynQ storage system.",
Expand Down Expand Up @@ -132,7 +134,7 @@ data class Product(
description = "List of attribute values for the product.",
example = "[{...}]"
)
val attributeValues: List<AttributeValue>,
val attributeValue: List<AttributeValue>,
@Schema(
description = "Position of the product in the TU, not used by us so it always have default values of '1,1,1'.",
example = "{...}"
Expand Down Expand Up @@ -187,3 +189,18 @@ data class Position(
)
val zPosition: Int
)

fun SynqBatchItemUpdatePayload.mapToItemPayloads(): List<MoveItemPayload> {
val list = mutableListOf<MoveItemPayload>()
for (product in loadUnit) {
list.add(
MoveItemPayload(
hostId = product.productId,
hostName = HostName.valueOf(product.hostName.uppercase()),
quantity = product.quantityOnHand,
location = location
)
)
}
return list
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import no.nb.mlt.wls.domain.model.Owner
import no.nb.mlt.wls.domain.ports.inbound.MoveItem
import no.nb.mlt.wls.domain.ports.inbound.OrderStatusUpdate
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
Expand All @@ -22,8 +23,20 @@ import org.springframework.web.bind.annotation.RestController
@RequestMapping(path = [ "/synq/v1"])
@Tag(name = "SynQ Controller", description = "API for receiving product and order updates from SynQ in Hermes WLS")
class SynqController(
private val moveItem: MoveItem,
private val orderStatusUpdate: OrderStatusUpdate
) {
@PutMapping("/item-update")
suspend fun updateItem(
@AuthenticationPrincipal jwt: JwtAuthenticationToken,
@RequestBody synqBatchItemUpdatePayload: SynqBatchItemUpdatePayload
): ResponseEntity<Void> {
for (payload in synqBatchItemUpdatePayload.mapToItemPayloads()) {
val item = moveItem.moveItem(payload)
println(item)
}
return ResponseEntity.ok().build()
}

@Operation(
summary = "Updates order status based on SynQ order status update",
Expand Down Expand Up @@ -64,12 +77,11 @@ class SynqController(
@PathVariable owner: Owner,
@Parameter(description = "Order ID in the storage system")
@PathVariable orderId: String
): ResponseEntity<Unit> {
): ResponseEntity<Void> {
orderStatusUpdate
.updateOrderStatus(orderUpdatePayload.hostName, orderId, orderUpdatePayload.getConvertedStatus())
?: return ResponseEntity.notFound().build()

return ResponseEntity.ok().build<Unit>()
return ResponseEntity.ok().build()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ enum class SynqOrderStatus {
STAGED
}

fun SynqOrderStatusUpdatePayload.getConvertedStatus() = when(status) {
SynqOrderStatus.NEW -> Order.Status.NOT_STARTED
SynqOrderStatus.COMPLETED -> Order.Status.COMPLETED
SynqOrderStatus.CANCELLED -> Order.Status.DELETED
else -> Order.Status.IN_PROGRESS
}
fun SynqOrderStatusUpdatePayload.getConvertedStatus() =
when (status) {
SynqOrderStatus.NEW -> Order.Status.NOT_STARTED
SynqOrderStatus.COMPLETED -> Order.Status.COMPLETED
SynqOrderStatus.CANCELLED -> Order.Status.DELETED
else -> Order.Status.IN_PROGRESS
}
11 changes: 8 additions & 3 deletions src/main/kotlin/no/nb/mlt/wls/domain/WLSService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,14 @@ class WLSService(
return itemRepository.getItem(hostName, hostId)
}

override suspend fun updateOrderStatus(hostName: HostName, hostOrderId: String, status: Order.Status): Order? {
val order = orderRepository.getOrder(hostName, hostOrderId)
?: throw OrderNotFoundException("No order with hostOrderId: $hostOrderId and hostName: $hostName exists")
override suspend fun updateOrderStatus(
hostName: HostName,
hostOrderId: String,
status: Order.Status
): Order? {
val order =
orderRepository.getOrder(hostName, hostOrderId)
?: throw OrderNotFoundException("No order with hostOrderId: $hostOrderId and hostName: $hostName exists")

return orderRepository.updateOrder(order.copy(status = status))
}
Expand Down
11 changes: 11 additions & 0 deletions src/main/kotlin/no/nb/mlt/wls/domain/ports/inbound/MoveItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ interface MoveItem {
quantity: Double,
location: String
): Item

suspend fun moveItem(moveItemPayload: MoveItemPayload): Item {
return moveItem(moveItemPayload.hostId, moveItemPayload.hostName, moveItemPayload.quantity, moveItemPayload.location)
}
}

data class MoveItemPayload(
val hostId: String,
val hostName: HostName,
val quantity: Double,
val location: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import no.nb.mlt.wls.domain.model.Item
import no.nb.mlt.wls.domain.model.Order

interface CallbackHandler {

fun handleItemCallback(item: Item)

fun handleOrderCallback(order: Order)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import no.nb.mlt.wls.domain.model.Item
import no.nb.mlt.wls.domain.model.Order
import no.nb.mlt.wls.domain.ports.outbound.CallbackHandler
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient

@Component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,25 @@ class ItemRepositoryMongoAdapter(
quantity: Double,
location: String
): Item {
mongoRepo
.findAndUpdateItemByHostNameAndHostId(hostId, hostName, quantity, location)
.timeout(Duration.ofSeconds(8))
.doOnError {
logger.error(it) {
if (it is TimeoutException) {
"Timed out while updating Item. Order ID: $hostId, Host: $hostName"
} else {
"Error while updating order"
val x =
mongoRepo
.findAndUpdateItemByHostNameAndHostId(hostName, hostId, quantity, location)
.timeout(Duration.ofSeconds(8))
.doOnError {
logger.error(it) {
if (it is TimeoutException) {
"Timed out while updating Item. Host ID: $hostId, Host: $hostName"
} else {
"Error while updating order"
}
}
}
}
.onErrorMap { ItemMovingException(it.message ?: "Item could not be moved", it) }
.awaitSingleOrNull() ?: ItemNotFoundException("Item with host ID $hostId for $hostName does not exist in WLS database")
.onErrorMap { ItemMovingException(it.message ?: "Item could not be moved", it) }
.awaitSingle()

if (x == 0L) {
throw ItemNotFoundException("Item was not found. Host ID: $hostId, Host: $hostName")
}

return getItem(hostName, hostId)!!
}
Expand All @@ -94,12 +99,12 @@ interface ItemMongoRepository : ReactiveMongoRepository<MongoItem, String> {
@Query(count = true, value = "{ '\$or': ?0 }")
fun countItemsMatchingIds(ids: List<ItemId>): Mono<Long>

@Query("{hostName: ?0, hostOrderId: ?1}")
@Query("{hostName: ?0,hostId: ?1}")
@Update("{'\$set':{quantity: ?2,location: ?3}}")
fun findAndUpdateItemByHostNameAndHostId(
hostOrderId: String,
hostName: HostName,
hostId: String,
quantity: Double,
location: String
): Mono<Void>
): Mono<Long>
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import no.nb.mlt.wls.domain.ports.outbound.StorageSystemException
import no.nb.mlt.wls.domain.ports.outbound.StorageSystemFacade
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.WebClientResponseException
import org.springframework.web.server.ServerErrorException
Expand Down
8 changes: 4 additions & 4 deletions src/test/kotlin/no/nb/mlt/wls/domain/WLSServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class WLSServiceTest {
coEvery { itemRepoMock.getItem(any(), any()) } returns testItem
coEvery { itemRepoMock.moveItem(any(), any(), any(), any()) } returns expectedItem

val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock)
val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock, callbackHandlerMock)
runTest {
val movedItem = cut.moveItem(testItem.hostId, testItem.hostName, 1.0, "Somewhere nice")
assertThat(movedItem).isEqualTo(expectedItem)
Expand All @@ -147,7 +147,7 @@ class WLSServiceTest {
fun `moveItem should fail when item does not exist`() {
coEvery { itemRepoMock.moveItem(any(), any(), any(), any()) } throws ItemNotFoundException("Item not found")

val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock)
val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock, callbackHandlerMock)
runTest {
assertThrows<RuntimeException> {
cut.moveItem(testItem.hostId, testItem.hostName, 1.0, "Somewhere nice")
Expand All @@ -163,7 +163,7 @@ class WLSServiceTest {
fun `moveItem throws when count is invalid`() {
coEvery { itemRepoMock.moveItem(any(), any(), -1.0, any()) } throws ValidationException("Location cannot be blank")

val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock)
val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock, callbackHandlerMock)
runTest {
assertThrows<RuntimeException> {
cut.moveItem(testItem.hostId, testItem.hostName, -1.0, "Somewhere nice")
Expand All @@ -179,7 +179,7 @@ class WLSServiceTest {
fun `moveItem throws when location is blank`() {
coEvery { itemRepoMock.moveItem(any(), any(), any(), any()) } throws ValidationException("Item not found")

val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock)
val cut = WLSService(itemRepoMock, orderRepoMock, storageSystemRepoMock, callbackHandlerMock)
runTest {
assertThrows<RuntimeException> {
cut.moveItem(testItem.hostId, testItem.hostName, 1.0, " ")
Expand Down

0 comments on commit 2ed3ffc

Please sign in to comment.