From b814fedeb77de80eef3656b71ec2e10ca9c3f210 Mon Sep 17 00:00:00 2001 From: Savosin Denis Date: Mon, 12 May 2025 15:19:40 +0700 Subject: [PATCH] move and refactor order service to core --- .../github/dannecron/demo/core/dto/Order.kt | 23 +++++ .../dannecron/demo/core/dto/OrderProduct.kt | 19 +++++ .../services/order/OrderProductService.kt | 9 ++ .../services/order/OrderProductServiceImpl.kt | 32 +++++++ .../demo/core/services/order/OrderService.kt | 11 +++ .../core/services/order/OrderServiceImpl.kt | 36 ++++++++ .../order/OrderProductServiceImplTest.kt | 80 ++++++++++++++++++ .../services/order/OrderServiceImplTest.kt | 84 +++++++++++++++++++ 8 files changed, 294 insertions(+) create mode 100644 core/src/main/kotlin/com/github/dannecron/demo/core/dto/Order.kt create mode 100644 core/src/main/kotlin/com/github/dannecron/demo/core/dto/OrderProduct.kt create mode 100644 core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductService.kt create mode 100644 core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImpl.kt create mode 100644 core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderService.kt create mode 100644 core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImpl.kt create mode 100644 core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImplTest.kt create mode 100644 core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImplTest.kt diff --git a/core/src/main/kotlin/com/github/dannecron/demo/core/dto/Order.kt b/core/src/main/kotlin/com/github/dannecron/demo/core/dto/Order.kt new file mode 100644 index 0000000..1793971 --- /dev/null +++ b/core/src/main/kotlin/com/github/dannecron/demo/core/dto/Order.kt @@ -0,0 +1,23 @@ +package com.github.dannecron.demo.core.dto + +import com.github.dannecron.demo.db.serialialization.OffsetDateTimeSerialization +import com.github.dannecron.demo.db.serialialization.UuidSerialization +import kotlinx.serialization.Serializable +import java.time.OffsetDateTime +import java.util.UUID + +@Serializable +data class Order( + val id: Long, + @Serializable(with = UuidSerialization::class) + val guid: UUID, + val customerId: Long, + @Serializable(with = OffsetDateTimeSerialization::class) + val deliveredAt: OffsetDateTime?, + @Serializable(with = OffsetDateTimeSerialization::class) + val createdAt: OffsetDateTime, + @Serializable(with = OffsetDateTimeSerialization::class) + val updatedAt: OffsetDateTime?, +) { + fun isDelivered(): Boolean = deliveredAt != null +} diff --git a/core/src/main/kotlin/com/github/dannecron/demo/core/dto/OrderProduct.kt b/core/src/main/kotlin/com/github/dannecron/demo/core/dto/OrderProduct.kt new file mode 100644 index 0000000..9995ad0 --- /dev/null +++ b/core/src/main/kotlin/com/github/dannecron/demo/core/dto/OrderProduct.kt @@ -0,0 +1,19 @@ +package com.github.dannecron.demo.core.dto + +import com.github.dannecron.demo.db.serialialization.OffsetDateTimeSerialization +import com.github.dannecron.demo.db.serialialization.UuidSerialization +import kotlinx.serialization.Serializable +import java.time.OffsetDateTime +import java.util.UUID + +@Serializable +data class OrderProduct( + @Serializable(with = UuidSerialization::class) + val guid: UUID, + val orderId: Long, + val productId: Long, + @Serializable(with = OffsetDateTimeSerialization::class) + val createdAt: OffsetDateTime, + @Serializable(with = OffsetDateTimeSerialization::class) + val updatedAt: OffsetDateTime?, +) diff --git a/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductService.kt b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductService.kt new file mode 100644 index 0000000..7a52bc4 --- /dev/null +++ b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductService.kt @@ -0,0 +1,9 @@ +package com.github.dannecron.demo.core.services.order + +import com.github.dannecron.demo.core.dto.Order +import com.github.dannecron.demo.core.dto.OrderProduct +import com.github.dannecron.demo.core.dto.Product + +interface OrderProductService { + fun create(order: Order, product: Product): OrderProduct +} diff --git a/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImpl.kt b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImpl.kt new file mode 100644 index 0000000..2afa831 --- /dev/null +++ b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImpl.kt @@ -0,0 +1,32 @@ +package com.github.dannecron.demo.core.services.order + +import com.github.dannecron.demo.core.dto.Order +import com.github.dannecron.demo.core.dto.OrderProduct +import com.github.dannecron.demo.core.dto.Product +import com.github.dannecron.demo.core.services.generation.CommonGenerator +import com.github.dannecron.demo.db.entity.order.OrderProductEntity +import com.github.dannecron.demo.db.repository.OrderProductRepository +import org.springframework.stereotype.Service + +@Service +class OrderProductServiceImpl( + private val orderProductRepository: OrderProductRepository, + private val commonGenerator: CommonGenerator +) : OrderProductService { + override fun create(order: Order, product: Product): OrderProduct = OrderProductEntity( + guid = commonGenerator.generateUUID(), + orderId = order.id, + productId = product.id, + createdAt = commonGenerator.generateCurrentTime(), + updatedAt = null, + ).let(orderProductRepository::save) + .toCore() + + private fun OrderProductEntity.toCore() = OrderProduct( + guid = guid, + orderId = orderId, + productId = productId, + createdAt = createdAt, + updatedAt = updatedAt, + ) +} diff --git a/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderService.kt b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderService.kt new file mode 100644 index 0000000..927190c --- /dev/null +++ b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderService.kt @@ -0,0 +1,11 @@ +package com.github.dannecron.demo.core.services.order + +import com.github.dannecron.demo.core.dto.Customer +import com.github.dannecron.demo.core.dto.Order + +interface OrderService { + + fun findByCustomerId(customerId: Long): List + + fun create(customer: Customer): Order +} diff --git a/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImpl.kt b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImpl.kt new file mode 100644 index 0000000..6f26a55 --- /dev/null +++ b/core/src/main/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImpl.kt @@ -0,0 +1,36 @@ +package com.github.dannecron.demo.core.services.order + +import com.github.dannecron.demo.core.dto.Customer +import com.github.dannecron.demo.core.dto.Order +import com.github.dannecron.demo.core.services.generation.CommonGenerator +import com.github.dannecron.demo.db.entity.order.OrderEntity +import com.github.dannecron.demo.db.repository.OrderRepository +import org.springframework.stereotype.Service + +@Service +class OrderServiceImpl( + private val orderRepository: OrderRepository, + private val commonGenerator: CommonGenerator, +) : OrderService { + override fun findByCustomerId(customerId: Long): List = + orderRepository.findByCustomerId(customerId).map { it.toCore() } + + override fun create(customer: Customer): Order = OrderEntity( + id = null, + guid = commonGenerator.generateUUID(), + customerId = customer.id, + deliveredAt = null, + createdAt = commonGenerator.generateCurrentTime(), + updatedAt = null, + ).let(orderRepository::save) + .toCore() + + private fun OrderEntity.toCore() = Order( + id = id!!, + guid = guid, + customerId = customerId, + deliveredAt = deliveredAt, + createdAt = createdAt, + updatedAt = updatedAt, + ) +} diff --git a/core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImplTest.kt b/core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImplTest.kt new file mode 100644 index 0000000..795f81b --- /dev/null +++ b/core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderProductServiceImplTest.kt @@ -0,0 +1,80 @@ +package com.github.dannecron.demo.core.services.order + +import com.github.dannecron.demo.core.dto.Order +import com.github.dannecron.demo.core.dto.OrderProduct +import com.github.dannecron.demo.core.dto.Product +import com.github.dannecron.demo.core.services.generation.CommonGenerator +import com.github.dannecron.demo.db.entity.order.OrderProductEntity +import com.github.dannecron.demo.db.repository.OrderProductRepository +import org.junit.jupiter.api.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import java.time.OffsetDateTime +import java.util.UUID +import kotlin.test.assertEquals + +class OrderProductServiceImplTest { + private val mockGuid = UUID.randomUUID() + private val mockCurrentTime = OffsetDateTime.now() + + private val orderProductRepository: OrderProductRepository = mock() + private val commonGenerator: CommonGenerator = mock { + on { generateUUID() } doReturn mockGuid + on { generateCurrentTime() } doReturn mockCurrentTime + } + + private val orderProductService = OrderProductServiceImpl( + orderProductRepository = orderProductRepository, + commonGenerator = commonGenerator + ) + + private val orderId = 22L + private val productId = 12L + private val order = Order( + id = orderId, + guid = UUID.randomUUID(), + customerId = 44L, + deliveredAt = null, + createdAt = OffsetDateTime.now(), + updatedAt = null, + ) + private val product = Product( + id = productId, + guid = UUID.randomUUID(), + name = "prod", + description = "some", + price = 10050, + createdAt = OffsetDateTime.now(), + updatedAt = null, + deletedAt = null + ) + private val orderProductEntity = OrderProductEntity( + guid = mockGuid, + orderId = orderId, + productId = productId, + createdAt = mockCurrentTime, + updatedAt = null, + ) + private val orderProduct = OrderProduct( + guid = mockGuid, + orderId = orderId, + productId = productId, + createdAt = mockCurrentTime, + updatedAt = null, + ) + + @Test + fun `create - success`() { + whenever(orderProductRepository.save(any())).thenReturn(orderProductEntity) + + val result = orderProductService.create(order, product) + + assertEquals(orderProduct, result) + + verify(orderProductRepository, times(1)).save(orderProductEntity) + } +} diff --git a/core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImplTest.kt b/core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImplTest.kt new file mode 100644 index 0000000..48d64c3 --- /dev/null +++ b/core/src/test/kotlin/com/github/dannecron/demo/core/services/order/OrderServiceImplTest.kt @@ -0,0 +1,84 @@ +package com.github.dannecron.demo.core.services.order + +import com.github.dannecron.demo.core.dto.Customer +import com.github.dannecron.demo.core.dto.Order +import com.github.dannecron.demo.core.services.generation.CommonGenerator +import com.github.dannecron.demo.db.entity.order.OrderEntity +import com.github.dannecron.demo.db.repository.OrderRepository +import org.junit.jupiter.api.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import java.time.OffsetDateTime +import java.util.UUID +import kotlin.test.assertEquals + +class OrderServiceImplTest { + private val mockGuid = UUID.randomUUID() + private val mockCurrentTime = OffsetDateTime.now() + + private val orderRepository: OrderRepository = mock() + private val commonGenerator: CommonGenerator = mock { + on { generateUUID() } doReturn mockGuid + on { generateCurrentTime() } doReturn mockCurrentTime + } + + private val orderService = OrderServiceImpl( + orderRepository = orderRepository, + commonGenerator = commonGenerator, + ) + + private val customerId = 123L + private val orderEntity = OrderEntity( + id = 22, + guid = mockGuid, + customerId = customerId, + deliveredAt = null, + createdAt = mockCurrentTime, + updatedAt = null, + ) + private val order = Order( + id = 22, + guid = mockGuid, + customerId = customerId, + deliveredAt = null, + createdAt = mockCurrentTime, + updatedAt = null, + ) + + private val customer = Customer( + id = customerId, + guid = UUID.randomUUID(), + name = "name", + cityId = null, + createdAt = OffsetDateTime.now(), + updatedAt = null, + ) + + @Test + fun `findByCustomerId - success`() { + whenever(orderRepository.findByCustomerId(any())).thenReturn(listOf(orderEntity)) + + val result = orderService.findByCustomerId(customerId) + + assertEquals(listOf(order), result) + + verify(orderRepository, times(1)).findByCustomerId(customerId) + } + + @Test + fun `create - success`() { + val orderEntityForCreation = orderEntity.copy(id = null) + + whenever(orderRepository.save(any())).thenReturn(orderEntity) + + val result = orderService.create(customer) + + assertEquals(order, result) + + verify(orderRepository, times(1)).save(orderEntityForCreation) + } +}