create city repository and service

This commit is contained in:
Denis Savosin
2024-10-01 16:51:28 +07:00
parent 0daff4065d
commit 1fa8b7051e
7 changed files with 144 additions and 5 deletions

View File

@@ -1,8 +1,11 @@
package com.example.demo package com.example.demo
import com.example.demo.provider.CityRepository
import com.example.demo.provider.MockedShopProvider import com.example.demo.provider.MockedShopProvider
import com.example.demo.provider.ProductRepository import com.example.demo.provider.ProductRepository
import com.example.demo.provider.ShopProvider import com.example.demo.provider.ShopProvider
import com.example.demo.services.CityService
import com.example.demo.services.CityServiceImpl
import com.example.demo.services.ProductService import com.example.demo.services.ProductService
import com.example.demo.services.ProductServiceImpl import com.example.demo.services.ProductServiceImpl
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
@@ -17,7 +20,8 @@ class AppConfig {
} }
@Bean @Bean
fun productService(@Autowired productRepository: ProductRepository): ProductService { fun productService(@Autowired productRepository: ProductRepository): ProductService = ProductServiceImpl(productRepository)
return ProductServiceImpl(productRepository = productRepository)
} @Bean
fun cityService(@Autowired cityRepository: CityRepository): CityService = CityServiceImpl(cityRepository)
} }

View File

@@ -1,15 +1,20 @@
package com.example.demo.models package com.example.demo.models
import com.example.demo.models.serializables.OffsetDateTimeSerialization import com.example.demo.models.serializables.OffsetDateTimeSerialization
import com.example.demo.models.serializables.UuidSerialization
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Column import org.springframework.data.relational.core.mapping.Column
import org.springframework.data.relational.core.mapping.Table import org.springframework.data.relational.core.mapping.Table
import java.time.OffsetDateTime import java.time.OffsetDateTime
import java.util.* import java.util.*
@Table("city") @Table("city")
@Serializable
data class City( data class City(
@Id
val id: Long?, val id: Long?,
@Serializable(with = UuidSerialization::class)
val guid: UUID, val guid: UUID,
val name: String, val name: String,
@Serializable(with = OffsetDateTimeSerialization::class) @Serializable(with = OffsetDateTimeSerialization::class)
@@ -21,4 +26,6 @@ data class City(
@Serializable(with = OffsetDateTimeSerialization::class) @Serializable(with = OffsetDateTimeSerialization::class)
@Column(value = "deleted_at") @Column(value = "deleted_at")
val deletedAt: OffsetDateTime?, val deletedAt: OffsetDateTime?,
) ) {
fun isDeleted(): Boolean = deletedAt != null
}

View File

@@ -0,0 +1,17 @@
package com.example.demo.provider
import com.example.demo.models.City
import org.springframework.data.jdbc.repository.query.Query
import org.springframework.data.repository.CrudRepository
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository
import java.time.OffsetDateTime
import java.util.*
@Repository
interface CityRepository: CrudRepository<City, Long> {
fun findByGuid(guid: UUID): City?
@Query(value = "UPDATE City SET deleted_at = :deletedAt WHERE guid = :guid RETURNING *")
fun softDelete(@Param("guid") guid: UUID, @Param("deletedAt") deletedAt: OffsetDateTime): City?
}

View File

@@ -0,0 +1,17 @@
package com.example.demo.services
import com.example.demo.exceptions.NotFoundException
import com.example.demo.exceptions.UnprocessableException
import com.example.demo.models.City
import org.springframework.stereotype.Service
import java.util.*
@Service
interface CityService {
fun findByGuid(guid: UUID): City?
fun create(name: String): City?
@Throws(NotFoundException::class, UnprocessableException::class)
fun delete(guid: UUID): City?
}

View File

@@ -0,0 +1,46 @@
package com.example.demo.services
import com.example.demo.exceptions.NotFoundException
import com.example.demo.exceptions.UnprocessableException
import com.example.demo.models.City
import com.example.demo.provider.CityRepository
import java.time.OffsetDateTime
import java.util.*
class CityServiceImpl(
private val cityRepository: CityRepository
): CityService {
override fun findByGuid(guid: UUID): City? = cityRepository.findByGuid(guid)
override fun create(name: String): City? {
val city = City(
id = null,
guid = UUID.randomUUID(),
name = name,
createdAt = OffsetDateTime.now(),
updatedAt = null,
deletedAt = null,
)
return cityRepository.save(city)
}
override fun delete(guid: UUID): City? {
val city = findByGuid(guid) ?: throw NotFoundException()
if (city.isDeleted()) {
throw UnprocessableException("city already deleted")
}
val deletedCity = city.copy(
id = city.id!!,
guid = city.guid,
name = city.name,
createdAt = city.createdAt,
updatedAt = city.updatedAt,
deletedAt = OffsetDateTime.now(),
)
return cityRepository.save(deletedCity)
}
}

View File

@@ -7,7 +7,9 @@ import com.example.demo.provider.ProductRepository
import java.time.OffsetDateTime import java.time.OffsetDateTime
import java.util.* import java.util.*
class ProductServiceImpl(private val productRepository: ProductRepository): ProductService { class ProductServiceImpl(
private val productRepository: ProductRepository,
): ProductService {
override fun findByGuid(guid: UUID): Product? = productRepository.findByGuid(guid) override fun findByGuid(guid: UUID): Product? = productRepository.findByGuid(guid)
override fun create(name: String, price: Long, description: String?): Product { override fun create(name: String, price: Long, description: String?): Product {

View File

@@ -0,0 +1,46 @@
package com.example.demo.services
import com.example.demo.BaseFeatureTest
import com.example.demo.models.City
import com.example.demo.provider.CityRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import kotlin.test.*
@ContextConfiguration(classes = [CityRepository::class, CityServiceImpl::class])
class CityServiceImplTest: BaseFeatureTest() {
@Autowired
private lateinit var cityRepository: CityRepository
@Autowired
private lateinit var cityServiceImpl: CityServiceImpl
@Test
fun createFindDelete_success() {
val name = "Some city"
var city: City? = null
try {
city = cityServiceImpl.create(name = name)
assertNotNull(city)
assertNotNull(city.id)
assertEquals(name, city.name)
val dbCity = cityServiceImpl.findByGuid(city.guid)
assertNotNull(dbCity)
assertEquals(city.id, dbCity.id)
assertFalse(dbCity.isDeleted())
val deletedCity = cityServiceImpl.delete(city.guid)
assertNotNull(deletedCity)
assertEquals(city.id, deletedCity.id)
assertNotNull(deletedCity.deletedAt)
assertTrue(deletedCity.isDeleted())
} finally {
val id = city?.id
if (id != null) {
cityRepository.deleteById(id)
}
}
}
}