Ajout du support pour les mélanges dans l'API REST.
This commit is contained in:
parent
c2c58be6bf
commit
ca5d489cc4
|
@ -1,10 +1,19 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.model
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
|
||||
import java.util.*
|
||||
import javax.persistence.*
|
||||
import javax.validation.constraints.NotBlank
|
||||
import javax.validation.constraints.NotNull
|
||||
|
||||
const val IDENTIFIER_MIX_TYPE_NAME = "mixType"
|
||||
|
||||
private const val MIX_ID_NULL_MESSAGE = "Un identifiant est requis"
|
||||
private const val MIX_NAME_NULL_MESSAGE = "Un nom est requis"
|
||||
private const val MIX_RECIPE_NULL_MESSAGE = "Un recette est requise"
|
||||
private const val MIX_MATERIAL_TYPE_NULL_MESSAGE = "Un type de prodsuit est requis"
|
||||
|
||||
@Entity
|
||||
data class Mix(
|
||||
@Id
|
||||
|
@ -13,27 +22,73 @@ data class Mix(
|
|||
|
||||
var location: String?,
|
||||
|
||||
@JsonIgnore
|
||||
@ManyToOne
|
||||
val recipe: Recipe,
|
||||
|
||||
@ManyToOne
|
||||
val mixType: MixType,
|
||||
@ManyToOne(cascade = [CascadeType.PERSIST])
|
||||
var mixType: MixType,
|
||||
|
||||
@OneToMany
|
||||
val mixMaterials: Collection<MixMaterial>,
|
||||
@OneToMany(cascade = [CascadeType.ALL])
|
||||
var mixMaterials: MutableCollection<MixMaterial>,
|
||||
) : Model {
|
||||
constructor(recipe: Recipe, mixType: MixType) : this(null, null, recipe, mixType, listOf())
|
||||
constructor(recipe: Recipe, mixType: MixType) : this(null, null, recipe, mixType, mutableListOf())
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is Mix && recipe == other.recipe && mixType == other.mixType
|
||||
override fun hashCode(): Int = Objects.hash(recipe, mixType)
|
||||
}
|
||||
|
||||
open class MixSaveDto(
|
||||
@field:NotBlank(message = MIX_NAME_NULL_MESSAGE)
|
||||
val name: String,
|
||||
|
||||
@field:NotNull(message = MIX_RECIPE_NULL_MESSAGE)
|
||||
val recipeId: Long,
|
||||
|
||||
@field:NotNull(message = MIX_MATERIAL_TYPE_NULL_MESSAGE)
|
||||
val materialTypeId: Long,
|
||||
|
||||
val mixMaterials: Map<Long, Float>?
|
||||
) : EntityDto<Mix> {
|
||||
override fun toEntity(): Mix = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
open class MixUpdateDto(
|
||||
@field:NotNull(message = MIX_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NullOrNotBlank(message = MIX_NAME_NULL_MESSAGE)
|
||||
val name: String?,
|
||||
|
||||
val materialType: MaterialType?,
|
||||
|
||||
val mixMaterials: Map<Long, Float>?
|
||||
) : EntityDto<Mix> {
|
||||
override fun toEntity(): Mix = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
// ==== DSL ====
|
||||
fun mix(
|
||||
id: Long? = null,
|
||||
location: String = "location",
|
||||
location: String? = "location",
|
||||
recipe: Recipe = recipe(),
|
||||
mixType: MixType = mixType(),
|
||||
mixMaterials: Collection<MixMaterial> = listOf(),
|
||||
mixMaterials: MutableCollection<MixMaterial> = mutableListOf(),
|
||||
op: Mix.() -> Unit = {}
|
||||
) = Mix(id, location, recipe, mixType, mixMaterials).apply(op)
|
||||
|
||||
fun mixSaveDto(
|
||||
name: String = "name",
|
||||
recipeId: Long = 0L,
|
||||
materialTypeId: Long = 0L,
|
||||
mixMaterials: Map<Long, Float>? = mapOf(),
|
||||
op: MixSaveDto.() -> Unit = {}
|
||||
) = MixSaveDto(name, recipeId, materialTypeId, mixMaterials).apply(op)
|
||||
|
||||
fun mixUpdateDto(
|
||||
id: Long = 0L,
|
||||
name: String? = "name",
|
||||
materialType: MaterialType? = materialType(),
|
||||
mixMaterials: Map<Long, Float>? = mapOf(),
|
||||
op: MixUpdateDto.() -> Unit = {}
|
||||
) = MixUpdateDto(id, name, materialType, mixMaterials).apply(op)
|
||||
|
|
|
@ -14,10 +14,15 @@ data class MixType(
|
|||
@Column(unique = true)
|
||||
override var name: String,
|
||||
|
||||
@ManyToOne
|
||||
var material: Material?
|
||||
@OneToOne(cascade = [CascadeType.ALL])
|
||||
var material: Material
|
||||
) : NamedModel {
|
||||
constructor(name: String, material: Material) : this(null, name, material)
|
||||
constructor(name: String, materialType: MaterialType) : this(
|
||||
null,
|
||||
name,
|
||||
material(name = name, inventoryQuantity = Float.MIN_VALUE, isMixType = true, materialType = materialType)
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is MixType && other.name == name && other.material == material
|
||||
override fun hashCode(): Int = Objects.hash(name, material)
|
||||
|
|
|
@ -42,7 +42,6 @@ data class Recipe(
|
|||
@ManyToOne
|
||||
val company: Company,
|
||||
|
||||
@JsonIgnore
|
||||
@OneToMany
|
||||
val mixes: MutableCollection<Mix>,
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.repository
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface MixRepository : JpaRepository<Mix, Long>
|
||||
interface MixRepository : JpaRepository<Mix, Long> {
|
||||
/** Finds all mixes with the given [mixType]. */
|
||||
fun findAllByMixType(mixType: MixType): Collection<Mix>
|
||||
}
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.rest
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.RecipePublicDataDto
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeSaveDto
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeUpdateDto
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.MixService
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.RecipeService
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.PutMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import java.net.URI
|
||||
import javax.validation.Valid
|
||||
|
||||
|
||||
private const val RECIPE_CONTROLLER_PATH = "api/recipe"
|
||||
private const val MIX_CONTROLLER_PATH = "api/recipe/mix"
|
||||
|
||||
@RestController
|
||||
@RequestMapping(RECIPE_CONTROLLER_PATH)
|
||||
|
@ -28,3 +25,23 @@ class RecipeController(recipeService: RecipeService) :
|
|||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(MIX_CONTROLLER_PATH)
|
||||
class MixController(val mixService: MixService) {
|
||||
@PostMapping
|
||||
fun save(@Valid @RequestBody entity: MixSaveDto): ResponseEntity<Mix> {
|
||||
val saved = mixService.save(entity)
|
||||
return ResponseEntity
|
||||
.created(URI("$MIX_CONTROLLER_PATH/${saved.id}"))
|
||||
.body(saved)
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
fun update(@Valid @RequestBody entity: MixUpdateDto): ResponseEntity<Void> {
|
||||
mixService.update(entity)
|
||||
return ResponseEntity
|
||||
.noContent()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,6 @@ interface MaterialService :
|
|||
/** Checks if a material with the given [materialType] exists. */
|
||||
fun existsByMaterialType(materialType: MaterialType): Boolean
|
||||
|
||||
/** Checks if the given [material] is used by one or more mixes. */
|
||||
fun isLinkedToMixes(material: Material): Boolean
|
||||
|
||||
/** Checks if the material with the given [id] has a SIMDUT file. */
|
||||
fun hasSimdut(id: Long): Boolean
|
||||
|
||||
|
@ -27,7 +24,6 @@ interface MaterialService :
|
|||
@Service
|
||||
class MaterialServiceImpl(
|
||||
materialRepository: MaterialRepository,
|
||||
val mixQuantityService: MixMaterialService,
|
||||
val simdutService: SimdutService
|
||||
) :
|
||||
AbstractExternalNamedModelService<Material, MaterialSaveDto, MaterialUpdateDto, MaterialRepository>(
|
||||
|
@ -37,7 +33,6 @@ class MaterialServiceImpl(
|
|||
override fun existsByMaterialType(materialType: MaterialType): Boolean =
|
||||
repository.existsByMaterialType(materialType)
|
||||
|
||||
override fun isLinkedToMixes(material: Material): Boolean = mixQuantityService.existsByMaterial(material)
|
||||
override fun hasSimdut(id: Long): Boolean = simdutService.exists(getById(id))
|
||||
override fun getSimdut(id: Long): ByteArray = simdutService.read(getById(id))
|
||||
override fun getAllNotMixType(): Collection<Material> = getAll().filter { !it.isMixType }
|
||||
|
|
|
@ -1,17 +1,35 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Material
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.mixMaterial
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixMaterialRepository
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
interface MixMaterialService : ModelService<MixMaterial, MixMaterialRepository> {
|
||||
/** Checks if one or more mix materials have the given [material]. */
|
||||
fun existsByMaterial(material: Material): Boolean
|
||||
|
||||
/** Creates [MixMaterial]s from the given [map]. The [map] must have the format <Material ID, Quantity>. */
|
||||
fun createFromMap(mix: Mix, map: Map<Long, Float>): Collection<MixMaterial>
|
||||
|
||||
/** Creates a [MixMaterial] from the given [pair]. The [pair] must have the format <Material ID, Quantity>. */
|
||||
fun createFromPair(mix: Mix, pair: Pair<Long, Float>): MixMaterial
|
||||
}
|
||||
|
||||
@Service
|
||||
class MixMaterialServiceImpl(mixMaterialRepository: MixMaterialRepository) :
|
||||
AbstractModelService<MixMaterial, MixMaterialRepository>(mixMaterialRepository), MixMaterialService {
|
||||
@Autowired
|
||||
lateinit var materialService: MaterialService
|
||||
|
||||
override fun existsByMaterial(material: Material): Boolean = repository.existsByMaterial(material)
|
||||
override fun createFromMap(mix: Mix, map: Map<Long, Float>): Collection<MixMaterial> = map.map { createFromPair(mix, it.toPair()) }
|
||||
|
||||
override fun createFromPair(mix: Mix, pair: Pair<Long, Float>): MixMaterial {
|
||||
val material = materialService.getById(pair.first)
|
||||
return mixMaterial(mix = mix, material = material, quantity = pair.second)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,80 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.stereotype.Service
|
||||
import javax.transaction.Transactional
|
||||
|
||||
interface MixService : ExternalModelService<Mix, MixSaveDto, MixUpdateDto, MixRepository> {
|
||||
/** Gets all mixes with the given [mixType]. */
|
||||
fun getAllByMixType(mixType: MixType): Collection<Mix>
|
||||
|
||||
/** Checks if a [MixType] is shared by several [Mix]es or not. */
|
||||
fun mixTypeIsShared(mixType: MixType): Boolean
|
||||
|
||||
interface MixService : ModelService<Mix, MixRepository> {
|
||||
/** Updates the location of the given [mix] to the given [location]. */
|
||||
fun updateLocation(mix: Mix, location: String)
|
||||
}
|
||||
|
||||
@Service
|
||||
class MixServiceImpl(mixRepository: MixRepository) : AbstractModelService<Mix, MixRepository>(mixRepository),
|
||||
class MixServiceImpl(
|
||||
mixRepository: MixRepository,
|
||||
@Lazy val recipeService: RecipeService,
|
||||
val materialTypeService: MaterialTypeService,
|
||||
val mixMaterialService: MixMaterialService,
|
||||
val mixTypeService: MixTypeService
|
||||
) : AbstractModelService<Mix, MixRepository>(mixRepository),
|
||||
MixService {
|
||||
override fun getAllByMixType(mixType: MixType): Collection<Mix> = repository.findAllByMixType(mixType)
|
||||
override fun mixTypeIsShared(mixType: MixType): Boolean = getAllByMixType(mixType).count() > 1
|
||||
|
||||
@Transactional
|
||||
override fun save(entity: MixSaveDto): Mix {
|
||||
val recipe = recipeService.getById(entity.recipeId)
|
||||
val materialType = materialTypeService.getById(entity.materialTypeId)
|
||||
val mixType = MixType(entity.name, materialType)
|
||||
|
||||
var mix = save(mix(recipe = recipe, mixType = mixType))
|
||||
val mixMaterials =
|
||||
if (entity.mixMaterials != null) mixMaterialService.createFromMap(mix, entity.mixMaterials) else listOf()
|
||||
mix = update(
|
||||
mix(
|
||||
id = mix.id,
|
||||
location = null,
|
||||
recipe = recipe,
|
||||
mixType = mixType,
|
||||
mixMaterials = mixMaterials.toMutableList()
|
||||
)
|
||||
)
|
||||
|
||||
recipeService.addMix(recipe, mix)
|
||||
|
||||
return mix
|
||||
}
|
||||
|
||||
override fun update(entity: MixUpdateDto): Mix {
|
||||
val mix = getById(entity.id)
|
||||
if (entity.name != null || entity.materialType != null) {
|
||||
mix.mixType = if (mixTypeIsShared(mix.mixType)) {
|
||||
mixTypeService.createForNameAndMaterialType(
|
||||
entity.name ?: mix.mixType.name,
|
||||
entity.materialType ?: mix.mixType.material.materialType!!
|
||||
)
|
||||
} else {
|
||||
mixTypeService.updateForNameAndMaterialType(
|
||||
mix.mixType,
|
||||
entity.name ?: mix.mixType.name,
|
||||
entity.materialType ?: mix.mixType.material.materialType!!
|
||||
)
|
||||
}
|
||||
}
|
||||
if (entity.mixMaterials != null) {
|
||||
mix.mixMaterials = mixMaterialService.createFromMap(mix, entity.mixMaterials).toMutableList()
|
||||
}
|
||||
return update(mix)
|
||||
}
|
||||
|
||||
override fun updateLocation(mix: Mix, location: String) {
|
||||
update(mix.apply { this.location = location })
|
||||
}
|
||||
|
|
|
@ -2,18 +2,28 @@ package dev.fyloz.trial.colorrecipesexplorer.service
|
|||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsRestException
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundRestException
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Material
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixTypeRepository
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
interface MixTypeService : NamedModelService<MixType, MixTypeRepository> {
|
||||
/** Gets the mix type with the given [material]. */
|
||||
fun getByMaterial(material: Material): MixType
|
||||
|
||||
/** Returns a new and persisted [MixType] with the given [name] and [materialType]. */
|
||||
fun createForNameAndMaterialType(name: String, materialType: MaterialType): MixType
|
||||
|
||||
/** Returns the given [mixType] updated with the given [name] and [materialType]. */
|
||||
fun updateForNameAndMaterialType(mixType: MixType, name: String, materialType: MaterialType): MixType
|
||||
}
|
||||
|
||||
@Service
|
||||
class MixTypeServiceImpl(mixTypeRepository: MixTypeRepository, private val materialService: MaterialService) :
|
||||
class MixTypeServiceImpl(
|
||||
mixTypeRepository: MixTypeRepository,
|
||||
val materialService: MaterialService,
|
||||
@Lazy val mixService: MixService
|
||||
) :
|
||||
AbstractNamedModelService<MixType, MixTypeRepository>(mixTypeRepository), MixTypeService {
|
||||
override fun getByMaterial(material: Material): MixType =
|
||||
repository.findByMaterial(material) ?: throw EntityNotFoundRestException(material.name)
|
||||
|
@ -23,4 +33,24 @@ class MixTypeServiceImpl(mixTypeRepository: MixTypeRepository, private val mater
|
|||
throw EntityAlreadyExistsRestException(entity.name)
|
||||
return super.save(entity)
|
||||
}
|
||||
|
||||
override fun createForNameAndMaterialType(name: String, materialType: MaterialType): MixType =
|
||||
save(
|
||||
mixType(
|
||||
name = name,
|
||||
material = material(
|
||||
name = name,
|
||||
inventoryQuantity = Float.MIN_VALUE,
|
||||
isMixType = true,
|
||||
materialType = materialType
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
override fun updateForNameAndMaterialType(mixType: MixType, name: String, materialType: MaterialType): MixType =
|
||||
update(mixType.apply {
|
||||
this.name = name
|
||||
material.name = name
|
||||
material.materialType = materialType
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,12 +2,10 @@ package dev.fyloz.trial.colorrecipesexplorer.service
|
|||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.isNotNullAndNotBlank
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.isNullOrNotBlank
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.or
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository
|
||||
import org.springframework.stereotype.Service
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
interface RecipeService : ExternalModelService<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeRepository> {
|
||||
/** Checks if one or more recipes have the given [company]. */
|
||||
|
@ -18,6 +16,9 @@ interface RecipeService : ExternalModelService<Recipe, RecipeSaveDto, RecipeUpda
|
|||
|
||||
/** Updates the public data of a recipe with the given [publicDateDto]. */
|
||||
fun updatePublicData(publicDataDto: RecipePublicDataDto)
|
||||
|
||||
/** Adds the given [mix] to the given [recipe]. */
|
||||
fun addMix(recipe: Recipe, mix: Mix): Recipe
|
||||
}
|
||||
|
||||
@Service
|
||||
|
@ -83,4 +84,7 @@ class RecipeServiceImpl(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun addMix(recipe: Recipe, mix: Mix) =
|
||||
update(recipe.apply { mixes.add(mix) })
|
||||
}
|
||||
|
|
|
@ -15,10 +15,9 @@ import kotlin.test.assertFalse
|
|||
import kotlin.test.assertTrue
|
||||
|
||||
class MaterialServiceTest : AbstractExternalNamedModelServiceTest<Material, MaterialSaveDto, MaterialUpdateDto, MaterialService, MaterialRepository>() {
|
||||
private val mixQuantityService: MixMaterialService = mock()
|
||||
private val simdutService: SimdutService = mock()
|
||||
override val repository: MaterialRepository = mock()
|
||||
override val service: MaterialService = spy(MaterialServiceImpl(repository, mixQuantityService, simdutService))
|
||||
override val service: MaterialService = spy(MaterialServiceImpl(repository, simdutService))
|
||||
|
||||
override val entity: Material = material(id = 0L, name = "material")
|
||||
override val anotherEntity: Material = material(id = 1L, name = "another material")
|
||||
|
@ -28,7 +27,7 @@ class MaterialServiceTest : AbstractExternalNamedModelServiceTest<Material, Mate
|
|||
|
||||
@AfterEach
|
||||
override fun afterEach() {
|
||||
reset(mixQuantityService, simdutService, entitySaveDto, entityUpdateDto)
|
||||
reset(simdutService)
|
||||
super.afterEach()
|
||||
}
|
||||
|
||||
|
@ -55,27 +54,6 @@ class MaterialServiceTest : AbstractExternalNamedModelServiceTest<Material, Mate
|
|||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class IsLinkedToMixes {
|
||||
@Test
|
||||
fun `returns true when a mix contains the given material in the repository`() {
|
||||
whenever(mixQuantityService.existsByMaterial(entity)).doReturn(true)
|
||||
|
||||
val found = service.isLinkedToMixes(entity)
|
||||
|
||||
assertTrue(found)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns false when no mix contains the given material in the repository`() {
|
||||
whenever(mixQuantityService.existsByMaterial(entity)).doReturn(false)
|
||||
|
||||
val found = service.isLinkedToMixes(entity)
|
||||
|
||||
assertFalse(found)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class HasSimdut {
|
||||
@Test
|
||||
|
|
|
@ -1,18 +1,74 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class MixServiceTest : AbstractModelServiceTest<Mix, MixService, MixRepository>() {
|
||||
class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpdateDto, MixService, MixRepository>() {
|
||||
override val repository: MixRepository = mock()
|
||||
override val service: MixService = spy(MixServiceImpl(repository))
|
||||
private val recipeService: RecipeService = mock()
|
||||
private val materialTypeService: MaterialTypeService = mock()
|
||||
private val mixMaterialService: MixMaterialService = mock()
|
||||
private val mixTypeService: MixTypeService = mock()
|
||||
override val service: MixService =
|
||||
spy(MixServiceImpl(repository, recipeService, materialTypeService, mixMaterialService, mixTypeService))
|
||||
|
||||
override val entity: Mix = mix(id = 0L, location = "location")
|
||||
override val anotherEntity: Mix = mix(id = 1L)
|
||||
override val entitySaveDto: MixSaveDto = spy(mixSaveDto(mixMaterials = mapOf(1L to 1000f)))
|
||||
override val entityUpdateDto: MixUpdateDto = spy(mixUpdateDto(id = entity.id!!))
|
||||
|
||||
@Nested
|
||||
inner class GetAllByMixType {
|
||||
@Test
|
||||
fun `returns all mixes with the given mix type`() {
|
||||
val mixType = mixType(id = 0L)
|
||||
|
||||
whenever(repository.findAllByMixType(mixType)).doReturn(entityList)
|
||||
|
||||
val found = service.getAllByMixType(mixType)
|
||||
|
||||
assertEquals(entityList, found)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveDto {
|
||||
@Test
|
||||
fun `calls and returns save() with the created entity`() {
|
||||
val recipe = recipe(id = entitySaveDto.recipeId)
|
||||
val materialType = materialType(id = entitySaveDto.materialTypeId)
|
||||
val material = material(
|
||||
name = entitySaveDto.name,
|
||||
inventoryQuantity = Float.MIN_VALUE,
|
||||
isMixType = true,
|
||||
materialType = materialType
|
||||
)
|
||||
val mixType = mixType(name = entitySaveDto.name, material = material)
|
||||
val mix = mix(recipe = recipe, mixType = mixType)
|
||||
val mixWithId = mix(id = 0L, recipe = recipe, mixType = mixType)
|
||||
val mixMaterials = listOf(mixMaterial(mix = mixWithId, material = material(id = 1L), quantity = 1000f))
|
||||
val mixWithMaterials = mix.apply { this.mixMaterials.addAll(mixMaterials) }
|
||||
|
||||
whenever(recipeService.getById(recipe.id!!)).doReturn(recipe)
|
||||
whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType)
|
||||
whenever(mixMaterialService.createFromMap(mixWithId, entitySaveDto.mixMaterials!!)).doReturn(mixMaterials)
|
||||
doReturn(true).whenever(service).existsById(mixWithId.id!!)
|
||||
doReturn(mixWithId).whenever(service).save(mix)
|
||||
doReturn(mixWithMaterials).whenever(service).update(mixWithMaterials)
|
||||
|
||||
val found = service.save(entitySaveDto)
|
||||
|
||||
verify(service).save(mix)
|
||||
verify(service).update(mixWithMaterials)
|
||||
verify(recipeService).addMix(recipe, mix)
|
||||
|
||||
assertEquals(mixWithMaterials, found)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdateLocation {
|
||||
|
|
|
@ -3,21 +3,20 @@ package dev.fyloz.trial.colorrecipesexplorer.service
|
|||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsRestException
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundRestException
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Material
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.material
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.mixType
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixTypeRepository
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService, MixTypeRepository>() {
|
||||
override val repository: MixTypeRepository = mock()
|
||||
private val materialService: MaterialService = mock()
|
||||
override val service: MixTypeService = spy(MixTypeServiceImpl(repository, materialService))
|
||||
private val mixService: MixService = mock()
|
||||
override val service: MixTypeService = spy(MixTypeServiceImpl(repository, materialService, mixService))
|
||||
|
||||
private val material: Material = material(id = 0L)
|
||||
override val entity: MixType = mixType(id = 0L, name = "mix type", material = material)
|
||||
|
@ -60,4 +59,46 @@ class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService
|
|||
assertEquals(entity.name, exception.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class CreateForNameAndMaterialType {
|
||||
@Test
|
||||
fun `creates a save a valid mix type with the given name and material type`() {
|
||||
val name = entity.name
|
||||
val materialType = materialType()
|
||||
|
||||
doAnswer { it.arguments[0] }.whenever(service).save(any())
|
||||
|
||||
val found = service.createForNameAndMaterialType(name, materialType)
|
||||
|
||||
verify(service).save(any())
|
||||
|
||||
assertEquals(name, found.name)
|
||||
assertEquals(name, found.material.name)
|
||||
assertEquals(materialType, found.material.materialType)
|
||||
assertTrue(found.material.isMixType)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdateForNameAndMaterialType {
|
||||
@Test
|
||||
fun `updates the given mix type with the given name and material type`() {
|
||||
val mixType = mixType(id = 1L, material = material(isMixType = true))
|
||||
val name = entity.name
|
||||
val materialType = materialType()
|
||||
|
||||
doAnswer { it.arguments[0] }.whenever(service).update(any())
|
||||
|
||||
val found = service.updateForNameAndMaterialType(mixType, name, materialType)
|
||||
|
||||
verify(service).update(any())
|
||||
|
||||
assertEquals(mixType.id, found.id)
|
||||
assertEquals(name, found.name)
|
||||
assertEquals(name, found.material.name)
|
||||
assertEquals(materialType, found.material.materialType)
|
||||
assertTrue(found.material.isMixType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,4 +93,22 @@ class RecipeServiceTest :
|
|||
verify(mixService).updateLocation(mix, location)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class AddMix {
|
||||
@Test
|
||||
fun `add the given mix to the given recipe and updates it`() {
|
||||
val mix = mix(id = 0L)
|
||||
val recipe = recipe(id = 0L, mixes = mutableListOf())
|
||||
|
||||
doAnswer { it.arguments[0] }.whenever(service).update(any<Recipe>())
|
||||
|
||||
val found = service.addMix(recipe, mix)
|
||||
|
||||
verify(service).update(any<Recipe>())
|
||||
|
||||
assertEquals(recipe.id, found.id)
|
||||
assertTrue(found.mixes.contains(mix))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue