Empêcher la création de mélanges avec le même nom qu'un produit
Les types de produit par défaut son maintenant définis dans les propriétés
This commit is contained in:
parent
58a60645b4
commit
5fa6cf1328
|
@ -29,6 +29,4 @@ HELP.md
|
|||
.vscode/
|
||||
|
||||
/logs/
|
||||
*.log
|
||||
/workdir/
|
||||
*.db
|
||||
|
|
3387
logs/cre.log
3387
logs/cre.log
File diff suppressed because it is too large
Load Diff
|
@ -1,12 +1,13 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.config.CREProperties;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.config.MaterialTypeProperties;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(MaterialTypeProperties.class)
|
||||
@EnableConfigurationProperties({MaterialTypeProperties.class, CREProperties.class})
|
||||
public class ColorRecipesExplorerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -15,4 +15,6 @@ public class Preferences {
|
|||
|
||||
public static String passwordsFileName;
|
||||
|
||||
public static String baseMaterialTypeName;
|
||||
|
||||
}
|
||||
|
|
|
@ -2,15 +2,18 @@ package dev.fyloz.trial.colorrecipesexplorer.core.configuration;
|
|||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.Preferences;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.config.CREProperties;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.config.MaterialTypeProperties;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.PasswordService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.files.FilesService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -18,37 +21,46 @@ import java.util.List;
|
|||
@Configuration
|
||||
public class SpringConfiguration {
|
||||
|
||||
@Value("${url.useport}")
|
||||
private boolean usePort;
|
||||
|
||||
@Value("${server.upload-directory}")
|
||||
private String uploadDirectory;
|
||||
|
||||
@Value("${server.passwords.file-name}")
|
||||
private String passwordsFileName;
|
||||
|
||||
private FilesService filesService;
|
||||
private MessageSource messageSource;
|
||||
private CREProperties creProperties;
|
||||
private MaterialTypeProperties materialTypeProperties;
|
||||
|
||||
@Autowired
|
||||
public SpringConfiguration(FilesService filesService, MessageSource messageSource) {
|
||||
public void setFilesService(FilesService filesService) {
|
||||
this.filesService = filesService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setMessageSource(MessageSource messageSource) {
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Qualifier("CREProperties")
|
||||
public void setCreProperties(CREProperties creProperties) {
|
||||
this.creProperties = creProperties;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setMaterialTypeProperties(MaterialTypeProperties materialTypeProperties) {
|
||||
this.materialTypeProperties = materialTypeProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public void setPreferences() {
|
||||
Preferences.urlUsePort = usePort;
|
||||
Preferences.uploadDirectory = uploadDirectory;
|
||||
Preferences.passwordsFileName = passwordsFileName;
|
||||
Preferences.urlUsePort = creProperties.isUrlUsePort();
|
||||
Preferences.uploadDirectory = creProperties.getUploadDirectory();
|
||||
Preferences.passwordsFileName = creProperties.getPasswordFile();
|
||||
Preferences.logger = LoggerFactory.getLogger(ColorRecipesExplorerApplication.class);
|
||||
Preferences.messageSource = messageSource;
|
||||
Preferences.baseMaterialTypeName = materialTypeProperties.getBaseName();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public void initializePasswords() {
|
||||
Logger logger = Preferences.logger;
|
||||
String filePath = filesService.getPath(passwordsFileName);
|
||||
String filePath = filesService.getPath(Preferences.passwordsFileName);
|
||||
|
||||
logger.info("Le fichier des utilisateurs se situe à: " + filesService.getFile(filePath).getAbsolutePath());
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import dev.fyloz.trial.colorrecipesexplorer.core.model.IModel;
|
|||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import javax.swing.text.html.parser.Entity;
|
||||
|
||||
@Getter
|
||||
public class EntityAlreadyExistsException extends ModelException {
|
||||
|
||||
|
@ -15,6 +17,10 @@ public class EntityAlreadyExistsException extends ModelException {
|
|||
@NonNull
|
||||
private Object requestedId;
|
||||
|
||||
public EntityAlreadyExistsException(EntityAlreadyExistsException ex) {
|
||||
this(ex.type, ex.identifierType, ex.identifierName, ex.requestedId);
|
||||
}
|
||||
|
||||
public EntityAlreadyExistsException(Class<? extends IModel> type, IdentifierType identifierType, Object requestedId) {
|
||||
super(type);
|
||||
this.identifierType = identifierType;
|
||||
|
|
|
@ -37,8 +37,4 @@ public class Material implements IModel {
|
|||
@ManyToOne
|
||||
private MaterialType materialType;
|
||||
|
||||
public boolean isMixType() {
|
||||
return isMixType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ import java.util.List;
|
|||
@NoArgsConstructor
|
||||
public class Mix implements IModel {
|
||||
|
||||
public static final String IDENTIFIER_MIX_TYPE_NAME = "mixType";
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
@Basic
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "cre.server")
|
||||
@Getter
|
||||
@Setter
|
||||
public class CREProperties {
|
||||
|
||||
private String passwordFile;
|
||||
private String uploadDirectory;
|
||||
private boolean urlUsePort;
|
||||
|
||||
}
|
|
@ -16,4 +16,6 @@ public class MaterialTypeProperties {
|
|||
|
||||
private List<MaterialType> defaults;
|
||||
|
||||
private String baseName;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model.dto;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MaterialType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MixType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class MixFormDto {
|
||||
|
||||
private Recipe recipe;
|
||||
|
@ -21,6 +24,4 @@ public class MixFormDto {
|
|||
|
||||
private List<Float> quantities;
|
||||
|
||||
public MixFormDto() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,11 +82,8 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
.withDto(formDto)
|
||||
.build();
|
||||
|
||||
if (materialService.existsByName(formDto.getMixTypeName()))
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, "materialName", formDto.getMixTypeName());
|
||||
|
||||
if (mix.getRecipe().hasMixType(mix.getMixType()))
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, "mixType", mix.getMixType());
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, Mix.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
|
||||
|
||||
mixTypeService.save(mix.getMixType());
|
||||
save(mix);
|
||||
|
@ -99,10 +96,12 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
.build();
|
||||
|
||||
MixType mixType = mix.getMixType();
|
||||
|
||||
if (!formDto.getOldMixTypeName().equals(mixType.getName()) && mixTypeService.existsByName(formDto.getMixTypeName()) && mix.getRecipe().hasMixType(mixTypeService.getByName(formDto.getMixTypeName())))
|
||||
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()))
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, "materialName", mixType.getName());
|
||||
if (!formDto.getOldMixTypeName().equals(mixType.getName()) && mix.getRecipe().hasMixType(mix.getMixType()))
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, "mixType", mix.getMixType());
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixType.IDENTIFIER_MATERIAL_NAME, mixType.getName());
|
||||
|
||||
update(mix);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import dev.fyloz.trial.colorrecipesexplorer.dao.MixTypeDao;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -26,6 +27,16 @@ public class MixTypeService extends GenericService<MixType, MixTypeDao> {
|
|||
this.materialService = materialService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un type de mélange correspondant à un nom existe.
|
||||
*
|
||||
* @param name Le nom du type de mélange
|
||||
* @return Si un type de mélange correspondant au nom existe
|
||||
*/
|
||||
public boolean existsByName(String name) {
|
||||
return dao.existsByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le type de mélange correspondant à un nom.
|
||||
*
|
||||
|
@ -65,6 +76,14 @@ public class MixTypeService extends GenericService<MixType, MixTypeDao> {
|
|||
return new MixType(name, mixTypeMaterial);
|
||||
}
|
||||
|
||||
@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());
|
||||
|
||||
return super.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MixType update(MixType mixType) {
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
|
||||
// Note
|
||||
recipe.setNote(note);
|
||||
save(recipe);
|
||||
update(recipe);
|
||||
|
||||
// Casiers
|
||||
for (Map.Entry<Long, String> location : locations.entrySet()) {
|
||||
|
|
|
@ -9,6 +9,9 @@ import java.util.Optional;
|
|||
|
||||
@Repository
|
||||
public interface MixTypeDao extends JpaRepository<MixType, Long> {
|
||||
|
||||
boolean existsByName(String name);
|
||||
|
||||
Optional<MixType> findByName(String name);
|
||||
|
||||
Optional<MixType> findByMaterial(Material material);
|
||||
|
|
|
@ -11,10 +11,7 @@ import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -53,7 +50,7 @@ public class RecipeExplorerController {
|
|||
|
||||
@PostMapping(value = EXPLORER_RECIPE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public Map<String, Object> saveRecipeInformations(RecipeExplorerFormDto form) {
|
||||
public Map<String, Object> saveRecipeInformations(@RequestBody RecipeExplorerFormDto form) {
|
||||
JSONResponseBuilder responseBuilder = new JSONResponseBuilder();
|
||||
|
||||
try {
|
||||
|
|
|
@ -6,6 +6,7 @@ import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilde
|
|||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MixType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.MixFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialTypeService;
|
||||
|
@ -64,15 +65,18 @@ public class MixEditorController {
|
|||
Mix mix = mixService.getById(id);
|
||||
|
||||
mixService.update(mix, formDto);
|
||||
|
||||
return modelResponseBuilder.build();
|
||||
} catch (EntityNotFoundException ex) {
|
||||
return getPage(modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id).build(), id);
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id).build();
|
||||
} catch (EntityAlreadyExistsException ex) {
|
||||
if (ex.getIdentifierName().equals("materialName"))
|
||||
return getPage(modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME).build(), id);
|
||||
if (ex.getIdentifierName().equals("mixType"))
|
||||
if (ex.getIdentifierName().equals(MixType.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());
|
||||
else throw new EntityAlreadyExistsException(ex);
|
||||
}
|
||||
|
||||
return modelResponseBuilder.build();
|
||||
return getPage(modelResponseBuilder.build(), id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,11 @@ spring.h2.console.settings.web-allow-others=true
|
|||
server.port=9090
|
||||
server.http2.enabled=true
|
||||
server.error.whitelabel.enabled=false
|
||||
server.upload-directory=./workdir
|
||||
server.passwords.file-name=passwords.txt
|
||||
|
||||
url.useport=true
|
||||
# CRE CONFIG
|
||||
cre.server.upload-directory=./workdir
|
||||
cre.server.password-file=passwords.txt
|
||||
cre.server.url-use-port=true
|
||||
|
||||
# DEFAULT MATERIAL TYPES
|
||||
entities.material-types.defaults[0].name=Aucun
|
||||
|
@ -35,6 +36,8 @@ entities.material-types.defaults[1].name=Base
|
|||
entities.material-types.defaults[1].prefix=BAS
|
||||
entities.material-types.defaults[1].use-percentages=false
|
||||
|
||||
entities.material-types.base-name=Base
|
||||
|
||||
# DEBUG
|
||||
spring.jpa.show-sql=true
|
||||
spring.h2.console.enabled=true
|
||||
|
|
|
@ -7,7 +7,7 @@ response.14=Le produit {0} est lié à une ou plusieurs recettes, veuillez les m
|
|||
response.15=La bannière {0} est liée à une ou plusieurs recettes, veuillez les supprimer d'abord
|
||||
response.16=Le mélange ayant l''identifiant {0} n''est pas associé à la recette ayant l''identifiant {1}
|
||||
response.17=Il n''y a pas assez de {0} en inventaire
|
||||
response.18=Cette recette contient déjà un mélange du type {0}
|
||||
response.18=Cette recette contient déjà un mélange de type {0}
|
||||
response.19=Aucun type de produit ayant le nom {0} n''a été trouvée
|
||||
response.2=Les informations de la recette ont été sauvegardées
|
||||
response.3=Une erreur est survenue lors de l''enregistrement
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<!-- Information nécessaire à la création des mélanges -->
|
||||
<input id="recipeId" name="recipe" th:value="${recipe.id}" type="hidden"/>
|
||||
<input id="mixId" name="mixId" th:value="${mix.id}" type="hidden"/>
|
||||
<input id="oldMixTypeName" name="oldMixTypeName" th:value="${mix.mixType.name}" type="hidden"/>
|
||||
|
||||
<div class="content">
|
||||
<div class="flexContent formWrap">
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
th:data-mixId="${mix.id}"
|
||||
th:data-quantityML="${mixQuantity.quantity}"
|
||||
th:data-usePercentages="${material.materialType.usePercentages}"
|
||||
th:data-isMixType="${material.isMixType}"
|
||||
th:data-isMixType="${material.isMixType()}"
|
||||
th:data-defaultvalue="${mixQuantity.quantity}"
|
||||
th:value="${mixQuantity.quantity}"
|
||||
th:readonly="${material.materialType.usePercentages}"
|
||||
|
@ -209,6 +209,7 @@
|
|||
</section>
|
||||
<!-- Fragment du pied de page -->
|
||||
<footer th:include="fragments.html :: footer(null, true)"></footer>
|
||||
<script th:include="fragments.html :: printStrings"></script>
|
||||
|
||||
<script>
|
||||
/*<![CDATA[*/
|
||||
|
@ -251,7 +252,7 @@
|
|||
$("#formSubmit").on({
|
||||
click: function () {
|
||||
let formData = {};
|
||||
formData.recipeID = $("#recipeId").val();
|
||||
formData.recipeId = $("#recipeId").val();
|
||||
|
||||
formData.locations = {};
|
||||
$(".recipeLocation").each(function () {
|
||||
|
@ -470,7 +471,6 @@
|
|||
|
||||
/*]]>*/
|
||||
</script>
|
||||
<script th:include="fragments.html :: printStrings"></script>
|
||||
<script type="module">
|
||||
/*<![CDATA[*/
|
||||
|
||||
|
@ -482,7 +482,7 @@
|
|||
|
||||
async function printMix(printButton) {
|
||||
const mixContainer = $(printButton).parents(".mixContainer");
|
||||
const allBases = $(mixContainer).find(".materialRow[data-materialtypename='[[${T(dev.fyloz.trial.colorrecipesexplorer.core.model.MaterialType).BASE_MATERIAL_TYPE.name}]]']");
|
||||
const allBases = $(mixContainer).find(".materialRow[data-materialtypename='[[${T(dev.fyloz.trial.colorrecipesexplorer.core.Preferences).baseMaterialTypeName}]]']");
|
||||
console.log(allBases.length + " bases trouvées");
|
||||
if (allBases.length <= 0) {
|
||||
showMessage(errorMsg, noBaseError);
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue