move and refactor city and product services to core

This commit is contained in:
Savosin Denis
2025-05-06 14:09:01 +07:00
parent b855aba506
commit f92ba7795d
18 changed files with 264 additions and 202 deletions

View File

@@ -1,19 +0,0 @@
package com.github.dannecron.demo.services.database.city
import com.github.dannecron.demo.db.entity.City
import com.github.dannecron.demo.services.database.exceptions.CityNotFoundException
import com.github.dannecron.demo.services.database.exceptions.AlreadyDeletedException
import com.github.dannecron.demo.services.kafka.dto.CityCreateDto
import org.springframework.stereotype.Service
import java.util.*
@Service
interface CityService {
fun findByGuid(guid: UUID): City?
fun create(name: String): City
fun create(kafkaCityDto: CityCreateDto): City
@Throws(CityNotFoundException::class, AlreadyDeletedException::class)
fun delete(guid: UUID): City
}

View File

@@ -1,60 +0,0 @@
package com.github.dannecron.demo.services.database.city
import com.github.dannecron.demo.core.services.generation.CommonGenerator
import com.github.dannecron.demo.db.entity.City
import com.github.dannecron.demo.db.repository.CityRepository
import com.github.dannecron.demo.services.database.exceptions.AlreadyDeletedException
import com.github.dannecron.demo.services.database.exceptions.CityNotFoundException
import com.github.dannecron.demo.services.kafka.dto.CityCreateDto
import org.springframework.stereotype.Service
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
import java.util.UUID
@Service
class CityServiceImpl(
private val cityRepository: CityRepository,
private val commonGenerator: CommonGenerator,
): CityService {
override fun findByGuid(guid: UUID): City? = cityRepository.findByGuid(guid)
override fun create(name: String): City = City(
id = null,
guid = commonGenerator.generateUUID(),
name = name,
createdAt = commonGenerator.generateCurrentTime(),
updatedAt = null,
deletedAt = null,
).let {
cityRepository.save(it)
}
override fun create(kafkaCityDto: CityCreateDto): City = City(
id = null,
guid = UUID.fromString(kafkaCityDto.guid),
name = kafkaCityDto.name,
createdAt = OffsetDateTime.parse(kafkaCityDto.createdAt, DateTimeFormatter.ISO_OFFSET_DATE_TIME),
updatedAt = kafkaCityDto.deletedAt?.let {
OffsetDateTime.parse(it, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
},
deletedAt = kafkaCityDto.deletedAt?.let {
OffsetDateTime.parse(it, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
},
).let {
cityRepository.save(it)
}
override fun delete(guid: UUID): City {
val city = findByGuid(guid) ?: throw CityNotFoundException()
if (city.isDeleted()) {
throw AlreadyDeletedException()
}
return cityRepository.save(
city.copy(
deletedAt = OffsetDateTime.now(),
)
)
}
}

View File

@@ -1,25 +0,0 @@
package com.github.dannecron.demo.services.database.product
import com.github.dannecron.demo.db.entity.Product
import com.github.dannecron.demo.services.database.exceptions.AlreadyDeletedException
import com.github.dannecron.demo.services.database.exceptions.ProductNotFoundException
import com.github.dannecron.demo.services.kafka.exceptions.InvalidArgumentException
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.util.UUID
@Service
interface ProductService {
fun findByGuid(guid: UUID): Product?
fun findAll(pageable: Pageable): Page<Product>
fun create(name: String, price: Long, description: String?): Product
@Throws(ProductNotFoundException::class, AlreadyDeletedException::class)
fun delete(guid: UUID): Product
@Throws(ProductNotFoundException::class, InvalidArgumentException::class)
fun syncToKafka(guid: UUID, topic: String?)
}

View File

@@ -1,82 +0,0 @@
package com.github.dannecron.demo.services.database.product
import com.github.dannecron.demo.core.services.generation.CommonGenerator
import com.github.dannecron.demo.db.entity.Product
import com.github.dannecron.demo.db.repository.ProductRepository
import com.github.dannecron.demo.services.database.exceptions.AlreadyDeletedException
import com.github.dannecron.demo.services.database.exceptions.ProductNotFoundException
import com.github.dannecron.demo.services.kafka.Producer
import com.github.dannecron.demo.services.kafka.dto.ProductDto
import com.github.dannecron.demo.services.kafka.exceptions.InvalidArgumentException
import com.github.dannecron.demo.utils.LoggerDelegate
import net.logstash.logback.marker.Markers
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.time.format.DateTimeFormatter
import java.util.UUID
@Service
class ProductServiceImpl(
private val productRepository: ProductRepository,
private val producer: Producer,
private val commonGenerator: CommonGenerator,
): ProductService {
private val logger by LoggerDelegate()
override fun findByGuid(guid: UUID): Product? = productRepository.findByGuid(guid)
.also {
logger.debug(
Markers.appendEntries(mapOf("guid" to guid, "idResult" to it?.id)),
"find product by guid",
)
}
override fun findAll(pageable: Pageable): Page<Product> = productRepository.findAll(pageable)
override fun create(name: String, price: Long, description: String?): Product {
val product = Product(
id = null,
guid = commonGenerator.generateUUID(),
name = name,
description = description,
price = price,
createdAt = commonGenerator.generateCurrentTime(),
updatedAt = null,
deletedAt = null,
)
return productRepository.save(product)
}
override fun delete(guid: UUID): Product {
val product = findByGuid(guid) ?: throw ProductNotFoundException()
if (product.isDeleted()) {
throw AlreadyDeletedException()
}
val deletedProduct = product.copy(
deletedAt = commonGenerator.generateCurrentTime(),
)
return productRepository.save(deletedProduct)
}
override fun syncToKafka(guid: UUID, topic: String?) {
val product = findByGuid(guid) ?: throw ProductNotFoundException()
producer.produceProductSync(product.toKafkaDto())
}
private fun Product.toKafkaDto() = ProductDto(
id = id ?: throw InvalidArgumentException("product.id"),
guid = guid.toString(),
name = name,
description = description,
price = price,
createdAt = createdAt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME),
updatedAt = updatedAt?.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME),
deletedAt = deletedAt?.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME),
)
}

View File

@@ -1,24 +0,0 @@
package com.github.dannecron.demo.utils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.full.companionObject
/**
* usage: `private val logger by LoggerDelegate()`
*/
class LoggerDelegate<in R : Any> : ReadOnlyProperty<R, Logger> {
override fun getValue(thisRef: R, property: KProperty<*>)
= getLogger(getClassForLogging(thisRef.javaClass))
private fun <T : Any> getClassForLogging(javaClass: Class<T>): Class<*> {
return javaClass.enclosingClass?.takeIf {
it.kotlin.companionObject?.java == javaClass
} ?: javaClass
}
}
fun getLogger(forClass: Class<*>): Logger = LoggerFactory.getLogger(forClass)