Ajout du support pour les types de produits en Kotlin.

This commit is contained in:
FyloZ 2021-01-08 19:03:27 -05:00
parent 37c10e6985
commit e56f185489
14 changed files with 167 additions and 96 deletions

View File

@ -1,50 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model;
import lombok.*;
import org.jetbrains.annotations.Nullable;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.Objects;
@Entity
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public class MixType implements Model {
public static final String IDENTIFIER_MATERIAL_NAME = "material";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@NonNull
@NotNull
private String name;
@NonNull
@NotNull
@ManyToOne(cascade = CascadeType.ALL)
private Material material;
public void setName(String name, boolean editMaterial) {
this.name = name;
if (editMaterial) this.material.setName(name);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MixType mixType = (MixType) o;
return Objects.equals(name, mixType.name) &&
Objects.equals(material, mixType.material);
}
@Override
public int hashCode() {
return Objects.hash(name, material);
}
}

View File

@ -1,18 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.repository;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface MixTypeRepository extends JpaRepository<MixType, Long> {
boolean existsByName(String name);
Optional<MixType> findByName(String name);
Optional<MixType> findByMaterial(Material material);
}

View File

@ -2,10 +2,7 @@ package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.model.*;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import dev.fyloz.trial.colorrecipesexplorer.utils.MixBuilder;
@ -23,7 +20,7 @@ public class MixService extends AbstractJavaService<Mix, MixRepository> {
private MaterialJavaService materialService;
private MixMaterialJavaService mixQuantityService;
private MixTypeService mixTypeService;
private MixTypeJavaService mixTypeService;
public MixService() {
super(Mix.class);
@ -45,7 +42,7 @@ public class MixService extends AbstractJavaService<Mix, MixRepository> {
}
@Autowired
public void setMixTypeService(MixTypeService mixTypeService) {
public void setMixTypeService(MixTypeJavaService mixTypeService) {
this.mixTypeService = mixTypeService;
}
@ -118,7 +115,7 @@ public class MixService extends AbstractJavaService<Mix, MixRepository> {
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, Mix.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
if (materialService.existsByName(mixType.getName()) && !materialService.getByName(mixType.getName()).isMixType())
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixType.IDENTIFIER_MATERIAL_NAME, mixType.getName());
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, mixType.getName());
mixTypeService.update(mixType);
update(mix);

View File

@ -4,10 +4,11 @@ import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsE
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
import dev.fyloz.trial.colorrecipesexplorer.repository.MixTypeRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -15,11 +16,11 @@ import javax.validation.constraints.NotNull;
import java.util.Optional;
@Service
public class MixTypeService extends AbstractJavaService<MixType, MixTypeRepository> {
public class MixTypeJavaService extends AbstractJavaService<MixType, MixTypeRepository> {
private MaterialJavaService materialService;
public MixTypeService() {
public MixTypeJavaService() {
super(MixType.class);
}
@ -50,7 +51,7 @@ public class MixTypeService extends AbstractJavaService<MixType, MixTypeReposito
* @return Le type de mélange correspondant au nom
*/
public MixType getByName(String name) {
Optional<MixType> found = repository.findByName(name);
Optional<MixType> found = findOptional(repository.findByName(name));
if (found.isEmpty()) throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, name);
return found.get();
@ -63,9 +64,9 @@ public class MixTypeService extends AbstractJavaService<MixType, MixTypeReposito
* @return Le type de mélange correspondant au produit
*/
public MixType getByMaterial(Material material) {
Optional<MixType> found = repository.findByMaterial(material);
Optional<MixType> found = findOptional(repository.findByMaterial(material));
if (found.isEmpty())
throw new EntityNotFoundException(type, ModelException.IdentifierType.OTHER, MixType.IDENTIFIER_MATERIAL_NAME, material);
throw new EntityNotFoundException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, material);
return found.get();
}
@ -85,7 +86,7 @@ public class MixTypeService extends AbstractJavaService<MixType, MixTypeReposito
@Override
public MixType save(@NotNull MixType entity) {
if (materialService.existsByName(entity.getName()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixType.IDENTIFIER_MATERIAL_NAME, entity.getName());
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, entity.getName());
return super.save(entity);
}

View File

@ -3,14 +3,14 @@ package dev.fyloz.trial.colorrecipesexplorer.utils;
import dev.fyloz.trial.colorrecipesexplorer.model.*;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixTypeService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixTypeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import java.util.*;
public class MixBuilder {
private MixTypeService mixTypeService;
private MixTypeJavaService mixTypeService;
private MaterialJavaService materialService;
private Long id;
@ -21,7 +21,7 @@ public class MixBuilder {
private Map<String, Float> quantities = new LinkedHashMap<>();
public MixBuilder(MixTypeService mixTypeService, MaterialJavaService materialService) {
public MixBuilder(MixTypeJavaService mixTypeService, MaterialJavaService materialService) {
this.mixTypeService = mixTypeService;
this.materialService = materialService;
}
@ -45,10 +45,11 @@ public class MixBuilder {
this.mixType = new MixType(this.mixType.getId(), this.mixType.getName(), this.mixType.getMaterial());
if (materialService.existsByName(mixTypeName)) {
this.mixType.setName(mixTypeName, false);
this.mixType.setName(mixTypeName);
this.mixType.setMaterial(materialService.getByName(mixTypeName));
} else {
this.mixType.setName(mixTypeName, true);
this.mixType.setName(mixTypeName);
this.mixType.getMaterial().setName(mixTypeName);
}
this.mixType.getMaterial().setMaterialType(dto.getMaterialType());

View File

@ -2,11 +2,11 @@ package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.ServiceKt;
@ -35,7 +35,7 @@ public class MixCreatorController {
private MaterialTypeJavaService materialTypeService;
@Autowired
public MixCreatorController(MixService mixService, RecipeService recipeService, MaterialJavaService materialService, MixTypeService mixTypeService, MaterialTypeJavaService materialTypeService) {
public MixCreatorController(MixService mixService, RecipeService recipeService, MaterialJavaService materialService, MixTypeJavaService mixTypeService, MaterialTypeJavaService materialTypeService) {
this.mixService = mixService;
this.recipeService = recipeService;
this.materialService = materialService;
@ -80,7 +80,7 @@ public class MixCreatorController {
} catch (EntityAlreadyExistsException ex) {
if (ex.getIdentifierName().equals(Mix.IDENTIFIER_MIX_TYPE_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
else if (ex.getIdentifierName().equals(MixType.IDENTIFIER_MATERIAL_NAME))
else if (ex.getIdentifierName().equals(MixTypeKt.IDENTIFIER_MATERIAL_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
}

View File

@ -2,11 +2,11 @@ package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
@ -72,7 +72,7 @@ public class MixEditorController {
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id).build();
} catch (EntityAlreadyExistsException ex) {
if (ex.getIdentifierName().equals(MixType.IDENTIFIER_MATERIAL_NAME))
if (ex.getIdentifierName().equals(MixTypeKt.IDENTIFIER_MATERIAL_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
else if (ex.getIdentifierName().equals(Mix.IDENTIFIER_MIX_TYPE_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());

View File

@ -29,7 +29,7 @@ data class MixMaterial(
// ==== DSL ====
fun mixMaterial(
id: Long? = 0L,
id: Long? = null,
mix: Mix = TODO(),
material: Material = material(),
quantity: Float = 0f,

View File

@ -0,0 +1,41 @@
package dev.fyloz.trial.colorrecipesexplorer.model
import java.util.*
import javax.persistence.*
const val IDENTIFIER_MATERIAL_NAME = "material"
@Entity
data class MixType(
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
override val id: Long?,
@Column(unique = true)
override var name: String,
@ManyToOne
var material: Material?
) : NamedModel {
constructor(name: String, material: Material) : this(null, name, material)
override fun equals(other: Any?): Boolean = other is MixType && other.name == name && other.material == material
override fun hashCode(): Int = Objects.hash(name, material)
}
// ==== DSL ====
fun mixType(
id: Long? = null,
name: String = "name",
material: Material = material(),
op: MixType.() -> Unit = {}
) = MixType(id, name, material).apply(op)
fun mixType(
name: String = "name",
materialType: MaterialType = materialType(),
op: MixType.() -> Unit = {}
) = MixType(
name,
material(name = name, inventoryQuantity = 0f, isMixType = true, materialType = materialType)
).apply(op)

View File

@ -0,0 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
import org.springframework.stereotype.Repository
@Repository
interface MixTypeRepository : NamedJpaRepository<MixType> {
/** Gets the mix type with the given [material]. */
fun findByMaterial(material: Material): MixType?
}

View File

@ -10,7 +10,7 @@ import org.springframework.stereotype.Service
const val minimumQuantity = 100.0f // TODO quantity stored in database
@Service
class InventoryService(val materialService: MaterialServiceImpl) {
class InventoryService(val materialService: MaterialService) {
fun getAllMaterials(): Collection<InventoryMaterial> {
return materialService.getAllNotMixType().map { it.toInventoryMaterial(minimumQuantity) }
}

View File

@ -3,7 +3,6 @@ package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MaterialRepository
import dev.fyloz.trial.colorrecipesexplorer.service.files.SimdutService
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixMaterialJavaService
import io.jsonwebtoken.lang.Assert
import org.springframework.stereotype.Service

View File

@ -0,0 +1,26 @@
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.repository.MixTypeRepository
import org.springframework.stereotype.Service
interface MixTypeService : NamedModelService<MixType, MixTypeRepository> {
/** Gets the mix type with the given [material]. */
fun getByMaterial(material: Material): MixType
}
@Service
class MixTypeServiceImpl(mixTypeRepository: MixTypeRepository, private val materialService: MaterialService) :
AbstractNamedModelService<MixType, MixTypeRepository>(mixTypeRepository), MixTypeService {
override fun getByMaterial(material: Material): MixType =
repository.findByMaterial(material) ?: throw EntityNotFoundRestException(material.name)
override fun save(entity: MixType): MixType {
if (materialService.existsByName(entity.name))
throw EntityAlreadyExistsRestException(entity.name)
return super.save(entity)
}
}

View File

@ -0,0 +1,63 @@
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.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
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 material: Material = material(id = 0L)
override val entity: MixType = mixType(id = 0L, name = "mix type", material = material)
override val anotherEntity: MixType = mixType(id = 1L, name = "another mix type")
override val entityWithEntityName: MixType = mixType(id = 2L, name = entity.name)
@AfterEach
override fun afterEach() {
reset(materialService)
super.afterEach()
}
@Nested
inner class GetByMaterial {
@Test
fun `returns the mix type with the given material`() {
whenever(repository.findByMaterial(material)).doReturn(entity)
val found = service.getByMaterial(material)
assertEquals(entity, found)
}
@Test
fun `throws EntityNotFoundRestException when no mix type with the given material exists`() {
whenever(repository.findByMaterial(material)).doReturn(null)
val exception = assertThrows<EntityNotFoundRestException> { service.getByMaterial(material) }
assertEquals(material.name, exception.value)
}
}
@Nested
inner class SaveMixType {
@Test
fun `throws EntityAlreadyExistsRestException when a material with the name of the new mix type exists`() {
whenever(materialService.existsByName(entity.name)).doReturn(true)
val exception = assertThrows<EntityAlreadyExistsRestException> { service.save(entity) }
assertEquals(entity.name, exception.value)
}
}
}