Début corrections: Impossible de créer plus que un (deux?) mélanges avec le même nom

This commit is contained in:
FyloZ 2020-03-08 22:39:55 -04:00
parent 2ba8d7ccb8
commit a47f82462d
14 changed files with 135 additions and 103 deletions

0
mvnw vendored Normal file → Executable file
View File

43
pom.xml
View File

@ -82,10 +82,6 @@
<scope>test</scope>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
@ -98,6 +94,16 @@
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.junit.jupiter</groupId>-->
<!-- <artifactId>junit-jupiter</artifactId>-->
<!-- <version>LATEST</version>-->
<!-- <scope>compile</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
</dependencies>
<build>
@ -107,21 +113,20 @@
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy file="start.bat" tofile="${basedir}/target/start.bat"/>
</tasks>
</configuration>
</execution>
</executions>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

View File

@ -6,12 +6,13 @@ import org.hibernate.annotations.ColumnDefault;
import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Objects;
@Entity
@Data
@EqualsAndHashCode(callSuper = false)
@RequiredArgsConstructor
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public class Material implements IModel {
@Id
@ -37,4 +38,17 @@ public class Material implements IModel {
@ManyToOne
private MaterialType materialType;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Material material = (Material) o;
return Objects.equals(id, material.id) &&
Objects.equals(name, material.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}

View File

@ -10,9 +10,9 @@ import java.util.Objects;
@Entity
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
@NoArgsConstructor
public class MaterialType implements IModel {
public static final String IDENTIFIER_PREFIX_NAME = "prefix";

View File

@ -4,12 +4,13 @@ import lombok.*;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.Objects;
@Entity
@Data
@EqualsAndHashCode(callSuper = false)
@RequiredArgsConstructor
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public class MixType implements IModel {
public static final String IDENTIFIER_MATERIAL_NAME = "material";
@ -24,11 +25,25 @@ public class MixType implements IModel {
@NonNull
@NotNull
@OneToOne(cascade = CascadeType.ALL)
@ManyToOne(cascade = CascadeType.ALL)
private Material material;
public void setName(String name) {
public void setName(String name, boolean editMaterial) {
this.name = name;
this.material.setName(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(id, mixType.id) &&
Objects.equals(name, mixType.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}

View File

@ -48,7 +48,7 @@ public class Recipe implements IModel {
private String note;
@JsonIgnore
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Mix> mixes;
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)

View File

@ -19,18 +19,18 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public abstract class AbstractService<T extends IModel, R extends JpaRepository<T, Long>> implements IGenericService<T> {
public abstract class AbstractService<E extends IModel, R extends JpaRepository<E, Long>> implements IGenericService<E> {
protected Logger logger = Preferences.logger;
protected R dao;
protected Class<T> type;
protected Class<E> type;
public AbstractService(Class<T> type) {
public AbstractService(Class<E> type) {
this.type = type;
}
@Override
public boolean exists(T entity) {
public boolean exists(E entity) {
return entity != null && entity.getId() != null && existsById(entity.getId());
}
@ -40,20 +40,20 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
}
@Override
public T getById(Long id) {
Optional<T> found = dao.findById(id);
public E getById(Long id) {
Optional<E> found = dao.findById(id);
if (found.isEmpty()) throw new EntityNotFoundException(type, EntityNotFoundException.IdentifierType.ID, id);
return found.get();
}
@Override
public List<T> getAll() {
public List<E> getAll() {
return dao.findAll();
}
@Override
public T save(@NotNull T entity) {
public E save(@NotNull E entity) {
if (entity.getId() != null && existsById(entity.getId()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.ID, entity.getId());
@ -62,7 +62,7 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
@Override
@Transactional
public Collection<T> saveAll(@NotNull Collection<T> entities) {
public Collection<E> saveAll(@NotNull Collection<E> entities) {
return entities
.stream()
.map(this::save)
@ -70,7 +70,7 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
}
@Override
public T update(@NonNull T entity) {
public E update(@NonNull E entity) {
if (entity.getId() == null) throw new NullIdentifierException(type);
if (!existsById(entity.getId()))
throw new EntityNotFoundException(type, ModelException.IdentifierType.ID, entity.getId());
@ -79,7 +79,7 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
}
@Override
public void delete(@NonNull T entity) {
public void delete(@NonNull E entity) {
dao.delete(entity);
}
@ -89,7 +89,7 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
}
@Override
public void deleteAll(List<T> entities) {
public void deleteAll(Collection<E> entities) {
dao.deleteAll(entities);
}
@ -100,7 +100,7 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
* @return Si l'entité est valide pour la création.
*/
@Deprecated(since = "1.3.0", forRemoval = true)
public boolean isValidForCreation(T entity) {
public boolean isValidForCreation(E entity) {
return entity != null && !existsById(entity.getId());
}
@ -111,7 +111,7 @@ public abstract class AbstractService<T extends IModel, R extends JpaRepository<
* @return Si l'entité est valide pour l'édition.
*/
@Deprecated(since = "1.3.0", forRemoval = true)
public boolean isValidForUpdate(@NonNull T entity) {
public boolean isValidForUpdate(@NonNull E entity) {
return entity.getId() != null && existsById(entity.getId());
}

View File

@ -76,5 +76,5 @@ public interface IGenericService<T extends IModel> {
*
* @param entities Les entités à supprimer
*/
void deleteAll(List<T> entities);
void deleteAll(Collection<T> entities);
}

View File

@ -43,6 +43,26 @@ public class MaterialService extends AbstractService<Material, MaterialDao> {
this.simdutService = simdutService;
}
/**
* Vérifie si un produit correspondant à un nom existe.
*
* @param name Le nom du produit
* @return Si un produit correspondant au nom existe
*/
public boolean existsByName(String name) {
return dao.existsByName(name);
}
/**
* Vérifie si des produits sont d'un type de produit
*
* @param materialType Le type de produit
* @return Si des produits sont du type de produit
*/
public boolean existsByMaterialType(MaterialType materialType) {
return dao.existsByMaterialType(materialType);
}
/**
* Vérifie si un produit est lié à un ou plusieurs mélanges.
*
@ -65,38 +85,6 @@ public class MaterialService extends AbstractService<Material, MaterialDao> {
.collect(Collectors.toList());
}
/**
* Vérifie si un produit correspondant à un nom existe.
*
* @param name Le nom du produit
* @return Si un produit correspondant au nom existe
*/
public boolean existsByName(String name) {
return dao.existsByName(name);
}
/**
* Vérifie si des produits sont d'un type de produit
*
* @param materialType Le type de produit
* @return Si des produits sont du type de produit
*/
public boolean existsByMaterialType(MaterialType materialType) {
return dao.existsByMaterialType(materialType);
}
/**
* Récupère tous les produits qui sont d'un type de produit.
*
* @param materialType Le type de produit des produits
* @return Tous les produits qui sont du type de produit
*/
public List<Material> getAllByMaterialType(MaterialType materialType) {
if (materialType == null) return new ArrayList<>();
return dao.findAllByMaterialType(materialType);
}
/**
* Récupère le produit correspondant à un nom.
*
@ -110,11 +98,6 @@ public class MaterialService extends AbstractService<Material, MaterialDao> {
return found.get();
}
@Override
public Material save(@NotNull Material material) {
return super.save(material);
}
public Material save(@NotNull Material material, MultipartFile file) {
simdutService.write(material, file);
@ -123,8 +106,8 @@ public class MaterialService extends AbstractService<Material, MaterialDao> {
@Override
public Material update(Material material) {
Optional<Material> materialByCode = dao.findByName(material.getName());
if (materialByCode.isPresent() && !material.getId().equals(materialByCode.get().getId()))
Optional<Material> materialByName = dao.findByName(material.getName());
if (materialByName.isPresent() && !material.getId().equals(materialByName.get().getId()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.NAME, material.getName());
return super.update(material);

View File

@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@ -37,6 +38,10 @@ public class MaterialTypeService extends AbstractService<MaterialType, MaterialT
this.materialService = materialService;
}
public void setDefaultMaterialTypes(List<MaterialType> defaultMaterialTypes) {
this.defaultMaterialTypes = defaultMaterialTypes;
}
/**
* Ajoute un type de produit dans les types de produit par défaut.
*
@ -83,7 +88,7 @@ public class MaterialTypeService extends AbstractService<MaterialType, MaterialT
* @return si le type de produit est utilisé par des produits.
*/
public boolean isLinkedToMaterials(MaterialType materialType) {
return !materialService.existsByMaterialType(materialType);
return materialService.existsByMaterialType(materialType);
}
/**
@ -104,17 +109,11 @@ public class MaterialTypeService extends AbstractService<MaterialType, MaterialT
* @return Le type de produit correspondant au nom.
*/
public MaterialType getByName(String name) {
return dao.findByName(name);
}
Optional<MaterialType> found = dao.findByName(name);
if(found.isEmpty())
throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, name);
/**
* Récupère un type de produit par son préfixe.
*
* @param prefix Le préfixe du type de produit à récupérer
* @return Le type de produit correspondant au préfixe
*/
public MaterialType getByPrefix(String prefix) {
return dao.findByPrefix(prefix);
return found.get();
}
public MaterialType update(MaterialTypeEditorDto materialTypeDto) {
@ -129,7 +128,7 @@ public class MaterialTypeService extends AbstractService<MaterialType, MaterialT
if (!materialTypeDto.getOldPrefix().equals(materialType.getPrefix()) && existsByPrefix(materialType.getPrefix()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MaterialType.IDENTIFIER_PREFIX_NAME, materialType.getPrefix());
return super.save(materialType);
return super.update(materialType);
}
@Override
@ -148,14 +147,14 @@ public class MaterialTypeService extends AbstractService<MaterialType, MaterialT
@Deprecated(since = "1.3.0", forRemoval = true)
public boolean isValidForUpdateName(MaterialType materialType) {
MaterialType materialTypeByName = dao.findByName(materialType.getName());
MaterialType materialTypeByName = dao.findByName(materialType.getName()).get();
return materialType.getId().equals(materialTypeByName.getId());
}
@Deprecated(since = "1.3.0", forRemoval = true)
public boolean isValidForUpdatePrefix(MaterialType materialType) {
MaterialType materialTypeByPrefix = dao.findByPrefix(materialType.getPrefix());
MaterialType materialTypeByPrefix = dao.findByPrefix(materialType.getPrefix()).get();
return materialType.getId().equals(materialTypeByPrefix.getId());
}

View File

@ -114,10 +114,10 @@ public class MixService extends AbstractService<Mix, MixDao> {
MixType mixType = mix.getMixType();
if (!formDto.getOldMixTypeName().equals(mixType.getName()) && mixTypeService.existsByName(formDto.getMixTypeName()) && mix.getRecipe().hasMixType(mixTypeService.getByName(formDto.getMixTypeName())))
if (!formDto.getOldMixTypeName().equals(mixType.getName()) && mixTypeService.existsByName(formDto.getMixTypeName()) && mix.getRecipe().hasMixType(mixType))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, Mix.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
if (materialService.existsByName(mixType.getName()) && !materialService.getByName(mixType.getName()).equals(mixType.getMaterial()))
if (materialService.existsByName(mixType.getName()) && !materialService.getByName(mixType.getName()).isMixType())
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixType.IDENTIFIER_MATERIAL_NAME, mixType.getName());
update(mix);

View File

@ -37,11 +37,21 @@ public class MixBuilder {
}
public MixBuilder withDto(MixFormDto dto) {
String mixTypeName = dto.getMixTypeName();
if (this.mixType == null) {
// this.mixType = mixTypeService.save(dto.getMixTypeName(), dto.getMaterialType());
this.mixType = mixTypeService.create(dto.getMixTypeName(), dto.getMaterialType());
this.mixType = mixTypeService.create(mixTypeName, dto.getMaterialType());
} else {
this.mixType.setName(dto.getMixTypeName());
this.mixType = new MixType(this.mixType.getId(), this.mixType.getName(), this.mixType.getMaterial());
// TODO le nom ne change pas
if (materialService.existsByName(mixTypeName)) {
this.mixType.setName(mixTypeName, false);
this.mixType.setMaterial(materialService.getByName(mixTypeName));
} else {
this.mixType.setName(mixTypeName, true);
}
this.mixType.getMaterial().setMaterialType(dto.getMaterialType());
}

View File

@ -3,14 +3,16 @@ package dev.fyloz.trial.colorrecipesexplorer.dao;
import dev.fyloz.trial.colorrecipesexplorer.core.model.MaterialType;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface MaterialTypeDao extends JpaRepository<MaterialType, Long> {
boolean existsByName(String name);
boolean existsByPrefix(String prefix);
MaterialType findByPrefix(String prefix);
Optional<MaterialType> findByPrefix(String prefix);
MaterialType findByName(String name);
Optional<MaterialType> findByName(String name);
}

View File

@ -1,3 +1,7 @@
# v1.3.1
### Corrections
* Correction d'un bug qui empêchait d'avoir plus que 2 mélanges avec le même nom.
# v1.3.0 (Optimisations back-end)
### Note: Cette mise à jour n'est pas compatible avec les anciennes versions.
### Corrections