Skip to content

Commit

Permalink
Create basic implementation for creating orders
Browse files Browse the repository at this point in the history
  • Loading branch information
anotheroneofthese committed Jul 29, 2024
1 parent ce2fd18 commit 615d7d4
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 9 deletions.
19 changes: 19 additions & 0 deletions src/main/kotlin/no/nb/mlt/wls/order/controller/OrderController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package no.nb.mlt.wls.order.controller

import no.nb.mlt.wls.order.payloads.ApiOrderPayload
import no.nb.mlt.wls.order.service.OrderService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping(path = ["", "/v1"])
class OrderController(val orderService: OrderService) {
// TODO - Swagger
@PostMapping("/order/batch/create")
fun createOrder(
@RequestBody payload: ApiOrderPayload
): ResponseEntity<ApiOrderPayload> = orderService.createOrder(payload)
}
27 changes: 19 additions & 8 deletions src/main/kotlin/no/nb/mlt/wls/order/payloads/SynqOrderPayload.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package no.nb.mlt.wls.order.payloads

import com.fasterxml.jackson.annotation.JsonFormat
import no.nb.mlt.wls.core.data.HostName
import no.nb.mlt.wls.core.data.synq.SynqOwner
import no.nb.mlt.wls.core.data.synq.toOwner
Expand All @@ -14,22 +15,24 @@ import java.time.LocalDateTime
data class SynqOrderPayload(
val orderId: String,
val orderType: SynqOrderType,
// "yyyy-MM-ddTHH:mm:ssZ"
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
val dispatchDate: LocalDateTime,
// "yyyy-MM-ddTHH:mm:ssZ"
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
val orderDate: LocalDateTime,
val priority: Int,
val owner: SynqOwner,
val orderLine: List<OrderLine>
) {
data class OrderLine(
// This must start at 1, it can NOT be zero
val orderLineNumber: Int,
val productId: String,
val quantityOrdered: Double
)

enum class SynqOrderType(private val type: String) {
STANDARD("Standard") ;
// FIXME - Update Serialization so that the enum can stay capitalized
Standard("Standard") ;

override fun toString(): String {
return type
Expand Down Expand Up @@ -73,15 +76,15 @@ fun Order.toSynqPayload() =
orderType = orderType.toSynqOrderType(),
// When order should be dispatched, AFAIK it's not used by us as we don't receive orders in future
dispatchDate = LocalDateTime.now(),
// When order was made in SynQ, if we want to we can ommit it and SynQ will set it to current date itself
// When order was made in SynQ, if we want to we can omit it and SynQ will set it to current date itself
orderDate = LocalDateTime.now(),
// TODO: we don't get it from API so we set it to 1, is other value more appropriate?
priority = 1,
owner = owner?.toSynqOwner() ?: SynqOwner.NB,
orderLine =
productLine.mapIndexed { index, it ->
SynqOrderPayload.OrderLine(
orderLineNumber = index,
orderLineNumber = index + 1,
productId = it.hostId,
quantityOrdered = 1.0
)
Expand All @@ -90,11 +93,19 @@ fun Order.toSynqPayload() =

fun SynqOrderPayload.SynqOrderType.toOrderType(): OrderType =
when (this) {
SynqOrderPayload.SynqOrderType.STANDARD -> OrderType.LOAN // TODO: Arbitrary mapping, need to discuss it with the team
SynqOrderPayload.SynqOrderType.Standard -> OrderType.LOAN // TODO: Arbitrary mapping, need to discuss it with the team
}

fun OrderType.toSynqOrderType(): SynqOrderPayload.SynqOrderType =
when (this) {
OrderType.LOAN -> SynqOrderPayload.SynqOrderType.STANDARD // TODO: Since mock api defined more types than Synq has we map both to standard
OrderType.DIGITIZATION -> SynqOrderPayload.SynqOrderType.STANDARD
OrderType.LOAN -> SynqOrderPayload.SynqOrderType.Standard // TODO: Since mock api defined more types than Synq has we map both to standard
OrderType.DIGITIZATION -> SynqOrderPayload.SynqOrderType.Standard
}

// TODO - Improve this

/**
* Utility classed used to wrap the payload.
* This is required for SynQ's specification of handling orders
*/
data class SynqOrder(val order: List<SynqOrderPayload>)
14 changes: 14 additions & 0 deletions src/main/kotlin/no/nb/mlt/wls/order/repository/OrderRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package no.nb.mlt.wls.order.repository

import no.nb.mlt.wls.core.data.HostName
import no.nb.mlt.wls.order.model.Order
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.stereotype.Repository

@Repository
interface OrderRepository : MongoRepository<Order, String> {
fun getByHostNameAndHostOrderId(
hostName: HostName,
hostOrderId: String
): Order?
}
36 changes: 36 additions & 0 deletions src/main/kotlin/no/nb/mlt/wls/order/service/OrderService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package no.nb.mlt.wls.order.service

import no.nb.mlt.wls.order.payloads.ApiOrderPayload
import no.nb.mlt.wls.order.payloads.toApiOrderPayload
import no.nb.mlt.wls.order.payloads.toOrder
import no.nb.mlt.wls.order.payloads.toSynqPayload
import no.nb.mlt.wls.order.repository.OrderRepository
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
import org.springframework.web.server.ServerErrorException

@Service
class OrderService(val db: OrderRepository, val synqService: SynqOrderService) {
fun createOrder(payload: ApiOrderPayload): ResponseEntity<ApiOrderPayload> {
// TODO - Order validation?

val existingOrder = db.getByHostNameAndHostOrderId(payload.hostName, payload.orderId)
if (existingOrder != null) {
return ResponseEntity.ok(existingOrder.toApiOrderPayload())
}

val synqResponse = synqService.createOrder(payload.toOrder().toSynqPayload())
if (!synqResponse.statusCode.is2xxSuccessful) {
return ResponseEntity.internalServerError().build()
}

try {
db.save(payload.toOrder())
} catch (e: Exception) {
throw ServerErrorException("Failed to save product in database, but created in storage system", e)
}

return ResponseEntity.status(HttpStatus.CREATED).build()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package no.nb.mlt.wls.order.service

import no.nb.mlt.wls.core.data.synq.SynqError
import no.nb.mlt.wls.order.payloads.SynqOrder
import no.nb.mlt.wls.order.payloads.SynqOrderPayload
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpEntity
Expand All @@ -22,8 +23,11 @@ class SynqOrderService {
fun createOrder(payload: SynqOrderPayload): ResponseEntity<SynqError> {
val uri = URI.create("$baseUrl/orders/batch")

// Wrap the order in the way SynQ likes it
val orders = SynqOrder(listOf(payload))

try {
return restTemplate.exchange(uri, HttpMethod.POST, HttpEntity(payload), SynqError::class.java)
return restTemplate.exchange(uri, HttpMethod.POST, HttpEntity(orders), SynqError::class.java)
} catch (e: HttpClientErrorException) {
val errorBody = e.getResponseBodyAs(SynqError::class.java)

Expand Down

0 comments on commit 615d7d4

Please sign in to comment.