Finalisation transition vers exceptions + DTO
This commit is contained in:
parent
26110beac2
commit
1b5480e800
|
@ -2,6 +2,7 @@ package dev.fyloz.trial.colorrecipesexplorer;
|
|||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.FileHandler;
|
||||
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;
|
||||
|
@ -25,6 +26,7 @@ public class ColorRecipesExplorerApplication {
|
|||
public static ColorRecipesExplorerApplication CREApp;
|
||||
|
||||
private MessageSource messageSource;
|
||||
private FilesService filesService;
|
||||
|
||||
public static void main(String[] args) {
|
||||
UPLOAD_LOCATION = args[0] != null ? args[0] : "./";
|
||||
|
@ -33,8 +35,9 @@ public class ColorRecipesExplorerApplication {
|
|||
}
|
||||
|
||||
@Autowired
|
||||
public ColorRecipesExplorerApplication(MessageSource messageSource) {
|
||||
public ColorRecipesExplorerApplication(MessageSource messageSource, FilesService filesService) {
|
||||
this.messageSource = messageSource;
|
||||
this.filesService = filesService;
|
||||
|
||||
CREApp = this;
|
||||
LOGGER.info("Le fichier des utilisateurs se situe à: " + new File(UPLOAD_LOCATION + "/" + USERS_FILE_NAME).getAbsolutePath());
|
||||
|
@ -48,16 +51,14 @@ public class ColorRecipesExplorerApplication {
|
|||
* Un mot de passe correspond à une ligne dans le fichier passwords.txt.
|
||||
*/
|
||||
private void loadPasswords() {
|
||||
FileHandler fileHandler = new FileHandler(USERS_FILE_NAME, FileHandler.FileContext.OTHERS, FileHandler.FileExtension.TEXT);
|
||||
if (!fileHandler.isValid()) {
|
||||
fileHandler.createFile();
|
||||
}
|
||||
String filePath = String.format("%s/%s.txt", UPLOAD_LOCATION, USERS_FILE_NAME);
|
||||
|
||||
try {
|
||||
List<String> fileContent = Files.readAllLines(fileHandler.getPath());
|
||||
if(filesService.fileExists(filePath)) filesService.createFile(filePath);
|
||||
List<String> fileContent = filesService.readFileAsStrings(filePath);
|
||||
|
||||
if (fileContent.size() < 1) {
|
||||
LOGGER.warn("Aucun mot de passe trouvé. Il sera impossible d'utiliser certaines fonctionnalitées de l'application.");
|
||||
LOGGER.warn("Aucun mot de passe trouvé. Il sera impossible d'utiliser certaines fonctionnalités de l'application.");
|
||||
}
|
||||
|
||||
for (String line : fileContent) {
|
||||
|
@ -65,7 +66,7 @@ public class ColorRecipesExplorerApplication {
|
|||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Une erreur est survenue lors du chargement du fichier des utilisateurs", e);
|
||||
LOGGER.warn("Il sera impossible d'utiliser certaines fonctionnalitées de l'application.");
|
||||
LOGGER.warn("Il sera impossible d'utiliser certaines fonctionnalités de l'application.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.configuration;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.ModelException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MaterialType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialTypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -10,8 +11,6 @@ import org.springframework.core.Ordered;
|
|||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class InitialDataLoader implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
@ -25,16 +24,17 @@ public class InitialDataLoader implements ApplicationListener<ApplicationReadyEv
|
|||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
||||
if (!materialTypeService.getByName(MaterialType.DEFAULT_MATERIAL_TYPE.getName()).isPresent())
|
||||
if (!materialTypeService.existsByName(MaterialType.DEFAULT_MATERIAL_TYPE.getName()))
|
||||
createInitialMaterialType(MaterialType.DEFAULT_MATERIAL_TYPE);
|
||||
if (!materialTypeService.getByName(MaterialType.BASE_MATERIAL_TYPE.getName()).isPresent())
|
||||
if (!materialTypeService.existsByName(MaterialType.BASE_MATERIAL_TYPE.getName()))
|
||||
createInitialMaterialType(MaterialType.BASE_MATERIAL_TYPE);
|
||||
}
|
||||
|
||||
private void createInitialMaterialType(MaterialType materialType) {
|
||||
Optional<MaterialType> optionalSavedMaterialType = materialTypeService.save(materialType);
|
||||
if (optionalSavedMaterialType.isEmpty()) {
|
||||
ColorRecipesExplorerApplication.LOGGER.warn(String.format("Échec de la création du type de produit par défaut '%s'.", materialType.getName()));
|
||||
try {
|
||||
materialTypeService.save(materialType);
|
||||
} catch (ModelException ex) {
|
||||
ColorRecipesExplorerApplication.LOGGER.warn(String.format("Échec de la création du type de produit par défaut '%s': %s", materialType.getName(), ex.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.exception.model;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.IModel;
|
||||
import org.hibernate.type.IdentifierType;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Représente une exception qui sera lancée lorsqu'un objet du modèle n'est pas trouvé.
|
||||
*/
|
||||
@Getter
|
||||
public class EntityNotFoundException extends ModelException {
|
||||
|
||||
/**
|
||||
|
@ -13,6 +14,11 @@ public class EntityNotFoundException extends ModelException {
|
|||
*/
|
||||
private IdentifierType identifierType;
|
||||
|
||||
/**
|
||||
* Le nom de l'identifiant utilisé (optionnel)
|
||||
*/
|
||||
private String identifierName;
|
||||
|
||||
/**
|
||||
* La valeur de l'identifiant
|
||||
*/
|
||||
|
@ -24,12 +30,10 @@ public class EntityNotFoundException extends ModelException {
|
|||
this.requestedId = requestedId;
|
||||
}
|
||||
|
||||
public IdentifierType getIdentifierType() {
|
||||
return identifierType;
|
||||
public EntityNotFoundException(Class<? extends IModel> type, IdentifierType identifierType, String identifierName, Object requestedId) {
|
||||
super(type);
|
||||
this.identifierType = identifierType;
|
||||
this.identifierName = identifierName != null ? identifierName : identifierType.getName();
|
||||
this.requestedId = requestedId;
|
||||
}
|
||||
|
||||
public Object getRequestedId() {
|
||||
return requestedId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,12 +27,12 @@ public class Material implements IModel {
|
|||
@NonNull
|
||||
@NotNull
|
||||
@ColumnDefault("0")
|
||||
private float inventoryQuantity;
|
||||
private Float inventoryQuantity;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ColumnDefault("false")
|
||||
private boolean isMixType;
|
||||
private Boolean isMixType;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
|
|
|
@ -12,6 +12,8 @@ import javax.validation.constraints.NotNull;
|
|||
@NoArgsConstructor
|
||||
public class MixType implements IModel {
|
||||
|
||||
public static final String IDENTIFIER_MATERIAL_NAME = "material";
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private Long id;
|
||||
|
|
|
@ -6,7 +6,9 @@ import org.hibernate.validator.constraints.Length;
|
|||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
|
@ -35,7 +37,7 @@ public class Recipe implements IModel {
|
|||
|
||||
@NonNull
|
||||
@NotNull
|
||||
private int sample;
|
||||
private Integer sample;
|
||||
|
||||
private String approbationDate;
|
||||
|
||||
|
@ -49,4 +51,12 @@ public class Recipe implements IModel {
|
|||
|
||||
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
private List<RecipeStep> recipeSteps;
|
||||
|
||||
public Collection<MixType> getMixTypes() {
|
||||
return mixes
|
||||
.stream()
|
||||
.map(Mix::getMixType)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -116,13 +116,12 @@ public class GenericService<T extends IModel, R extends JpaRepository<T, Long>>
|
|||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "v.1.3.0", forRemoval = true)
|
||||
public boolean exists(T entity) {
|
||||
return entity != null && entity.getId() != null && existsById(entity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean existsById(Long id) {
|
||||
public boolean existsById(Long id) {
|
||||
return dao.existsById(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Material;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MixQuantity;
|
||||
|
@ -38,7 +39,12 @@ public class InventoryService {
|
|||
|
||||
if (!material.isMixType()) {
|
||||
material.setInventoryQuantity(material.getInventoryQuantity() - entry.getValue());
|
||||
if (materialService.update(material).isEmpty()) return false;
|
||||
|
||||
try {
|
||||
materialService.update(material);
|
||||
} catch (EntityNotFoundException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.io.InputStream;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class FilesService {
|
||||
|
@ -65,6 +66,17 @@ public class FilesService {
|
|||
return Files.readAllBytes(Paths.get(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le contenu d'un fichier dans une liste de String.
|
||||
*
|
||||
* @param path Le chemin vers le fichier
|
||||
* @return Le contenu du fichier dans une liste de String
|
||||
* @throws IOException La lecture du fichier a échoué
|
||||
*/
|
||||
public List<String> readFileAsStrings(String path) throws IOException {
|
||||
return Files.readAllLines(Paths.get(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Écrit un fichier Multipart sur le disque.
|
||||
*
|
||||
|
@ -93,7 +105,7 @@ public class FilesService {
|
|||
* @throws IOException La création du fichier échoue
|
||||
*/
|
||||
public File createFile(String path) throws IOException {
|
||||
File file = new File(path);
|
||||
File file = getFile(path);
|
||||
|
||||
if (!file.exists() || file.isDirectory()) {
|
||||
Files.createDirectories(file.getParentFile().toPath());
|
||||
|
@ -110,7 +122,7 @@ public class FilesService {
|
|||
* @throws IOException La suppression du fichier échoue
|
||||
*/
|
||||
public void deleteFile(String path) {
|
||||
File file = new File(path);
|
||||
File file = getFile(path);
|
||||
|
||||
try {
|
||||
if (file.exists() && !file.isDirectory()) Files.delete(file.toPath());
|
||||
|
@ -119,4 +131,20 @@ public class FilesService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un fichier existe sur le disque.
|
||||
*
|
||||
* @param path Le chemin vers le fichier
|
||||
* @return Si le fichier existe
|
||||
*/
|
||||
public boolean fileExists(String path) {
|
||||
File file = getFile(path);
|
||||
|
||||
return file.exists() && !file.isDirectory();
|
||||
}
|
||||
|
||||
private File getFile(String path) {
|
||||
return new File(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ package dev.fyloz.trial.colorrecipesexplorer.core.services.files;
|
|||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Service
|
||||
public class ImagesService {
|
||||
|
@ -26,6 +30,26 @@ public class ImagesService {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean writeMultipartImage(MultipartFile image, String name) {
|
||||
return filesService.writeMultiPartFile(image, getPath(name));
|
||||
}
|
||||
|
||||
public void deleteImage(String name) {
|
||||
filesService.deleteFile(getPath(name));
|
||||
}
|
||||
|
||||
public boolean isImage(InputStream input) {
|
||||
try {
|
||||
return !(ImageIO.read(input) == null);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Erreur lors de la vérification d'une image: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public File getDirectoryFile() {
|
||||
return new File(getPath(""));
|
||||
}
|
||||
|
||||
private String getPath(String name) {
|
||||
return String.format("%s/%s/%s", ColorRecipesExplorerApplication.UPLOAD_LOCATION, IMAGES_DIRECTORY, name);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.files;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Material;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Service
|
||||
public class SimdutService {
|
||||
|
||||
private static final String SIMDUT_DIRECTORY = "simdut";
|
||||
|
||||
private FilesService filesService;
|
||||
private MaterialService materialService;
|
||||
|
||||
@Autowired
|
||||
public SimdutService(FilesService filesService, MaterialService materialService) {
|
||||
this.filesService = filesService;
|
||||
this.materialService = materialService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lit le fichier SIMDUT d'un produit et retourne son contenu.
|
||||
*
|
||||
* @param material Le produit
|
||||
* @return Le contenu du fichier SIMDUT du produit
|
||||
*/
|
||||
public byte[] readSimdutForMaterial(Material material) {
|
||||
String path = getPath(material);
|
||||
|
||||
if (filesService.fileExists(path)) return new byte[0];
|
||||
|
||||
try {
|
||||
return filesService.readFileAsBytes(path);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Impossible de lire un fichier SIMDUT: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lit le fichier SIMDUT du produit correspondant à un identifiant et retourne son contenu.
|
||||
*
|
||||
* @param id L'identifiant du produit
|
||||
* @return Le contenu du fichier SIMDUT du produit correspondant à l'identifiant
|
||||
*/
|
||||
public byte[] readSimdutForMaterialId(Long id) {
|
||||
return readSimdutForMaterial(materialService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un produit a un fichier SIMDUT.
|
||||
*
|
||||
* @param material Le produit
|
||||
* @return Si le produit a un fichier SIMDUT
|
||||
*/
|
||||
public boolean simdutExistsForMaterial(Material material) {
|
||||
return filesService.fileExists(getPath(material));
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le produit correspondant à un identifiant a un fichier SIMDUT.
|
||||
*
|
||||
* @param id L'identifiant du produit
|
||||
* @return si le produit correspondant à l'identifiant a un fichier SIMDUT
|
||||
*/
|
||||
public boolean simdutExistsForMaterialId(Long id) {
|
||||
return simdutExistsForMaterial(materialService.getById(id));
|
||||
}
|
||||
|
||||
private String getPath(Material material) {
|
||||
return String.format("%s/%s/%s", ColorRecipesExplorerApplication.UPLOAD_LOCATION, SIMDUT_DIRECTORY, materialService.getSimdutFileName(material));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.files;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.xlsx.XlsxExporter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Service
|
||||
public class XlsService {
|
||||
|
||||
private RecipeService recipeService;
|
||||
|
||||
@Autowired
|
||||
public XlsService(RecipeService recipeService) {
|
||||
this.recipeService = recipeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère le fichier XLS d'une recette.
|
||||
*
|
||||
* @param recipe La recette
|
||||
* @return Le fichier XLS de la recette
|
||||
*/
|
||||
public byte[] generateXlsForRecipe(Recipe recipe) {
|
||||
return new XlsxExporter().generate(recipe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère le fichier XLS de la recette correspondant à l'identifiant.
|
||||
*
|
||||
* @param id L'identifiant de la recette
|
||||
* @return Le fichier XLS de la recette
|
||||
*/
|
||||
public byte[] generateXlsForRecipeId(Long id) {
|
||||
return generateXlsForRecipe(recipeService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère les fichiers XLS de toutes les recettes et les écrit dans un fichier ZIP.
|
||||
*
|
||||
* @return Le fichier ZIP contenant tous les fichiers XLS
|
||||
*/
|
||||
public byte[] generateXlsForAllRecipes() {
|
||||
ColorRecipesExplorerApplication.LOGGER.info("Exportation de toutes les couleurs en XLS");
|
||||
|
||||
Collection<Recipe> recipes = recipeService.getAll();
|
||||
try (ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); ZipOutputStream zipOutput = new ZipOutputStream(byteOutput)) {
|
||||
for (Recipe recipe : recipes) {
|
||||
byte[] recipeXLS = generateXlsForRecipe(recipe);
|
||||
zipOutput.putNextEntry(new ZipEntry(String.format("%s_%s.xlsx", recipe.getCompany().getName(), recipe.getName())));
|
||||
zipOutput.write(recipeXLS, 0, recipeXLS.length);
|
||||
zipOutput.closeEntry();
|
||||
}
|
||||
|
||||
return byteOutput.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Impossible d'exporter toutes les recettes vers le format XLS: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,10 +34,6 @@ public class MaterialService extends GenericService<Material, MaterialDao> {
|
|||
this.filesService = filesService;
|
||||
}
|
||||
|
||||
public Optional<Material> getByName(String name) {
|
||||
return dao.findByName(name);
|
||||
}
|
||||
|
||||
public List<Material> getAllByMaterialType(MaterialType materialType) {
|
||||
if (materialType == null) return new ArrayList<>();
|
||||
|
||||
|
@ -77,6 +73,12 @@ public class MaterialService extends GenericService<Material, MaterialDao> {
|
|||
return super.update(material);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Material material) {
|
||||
removeSimdut(material);
|
||||
super.delete(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un produit est lié à un ou plusieurs mélanges.
|
||||
*
|
||||
|
@ -94,30 +96,6 @@ public class MaterialService extends GenericService<Material, MaterialDao> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Material material) {
|
||||
return material != null && (super.exists(material) || dao.existsByName(material.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidForUpdate(Material material) {
|
||||
if (material == null) return false;
|
||||
|
||||
Optional<Material> materialByCode = dao.findByName(material.getName());
|
||||
return super.isValidForUpdate(material) && (materialByCode.isEmpty() || material.getId().equals(materialByCode.get().getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un FileHandler pour le produit passé en paramètre.
|
||||
*
|
||||
* @param material Le produit dont on veut créer un FileHandler
|
||||
* @return Le FileHandler correspondant au produit.
|
||||
*/
|
||||
private FileHandler getFileHandlerForMaterial(Material material) {
|
||||
String filename = String.format("%s_%s", material.getId(), material.getName());
|
||||
return new FileHandler(filename, FileHandler.FileContext.SIMDUT, FileHandler.FileExtension.PDF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le chemin vers le fichier SIMDUT d'un produit.
|
||||
*
|
||||
|
@ -165,4 +143,8 @@ public class MaterialService extends GenericService<Material, MaterialDao> {
|
|||
public void removeSimdut(Material material) {
|
||||
filesService.deleteFile(getSimdutPath(material));
|
||||
}
|
||||
|
||||
public String getSimdutFileName(Material material) {
|
||||
return String.format("%s_%s", material.getId(), material.getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ public class MixQuantityService extends GenericService<MixQuantity, MixQuantityD
|
|||
|
||||
@Autowired
|
||||
public MixQuantityService(MixQuantityDao mixQuantityDao) {
|
||||
super(mixQuantityDao);
|
||||
super(mixQuantityDao, MixQuantity.class);
|
||||
}
|
||||
|
||||
public boolean existsByMaterial(Material material) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.model;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.MixCreationFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.GenericService;
|
||||
|
@ -11,38 +10,37 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.StringBank.MATERIALS;
|
||||
|
||||
@Service
|
||||
public class MixService extends GenericService<Mix, MixDao> {
|
||||
|
||||
private MaterialService materialService;
|
||||
private MixQuantityService mixQuantityService;
|
||||
private MixTypeService mixTypeService;
|
||||
private RecipeService recipeService;
|
||||
|
||||
@Autowired
|
||||
public MixService(MixDao mixDao, MaterialService materialService, MixQuantityService mixQuantityService, MixTypeService mixTypeService, RecipeService recipeService) {
|
||||
public MixService(MixDao mixDao, MaterialService materialService, MixQuantityService mixQuantityService, MixTypeService mixTypeService) {
|
||||
super(mixDao, Mix.class);
|
||||
this.materialService = materialService;
|
||||
this.mixQuantityService = mixQuantityService;
|
||||
this.mixTypeService = mixTypeService;
|
||||
this.recipeService = recipeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les produits disponibles pour un mélange.
|
||||
* Le mélange peut ne pas exister.
|
||||
*
|
||||
* @param recipeId L'identifiant de la recette dans laquelle se trouve le mélange
|
||||
* @param mixId L'identifiant du mélange (-1 si le mélange n'existe pas)
|
||||
* @param recipe La recette dans laquelle se trouve le mélange
|
||||
* @param mixId L'identifiant du mélange (-1 si le mélange n'existe pas)
|
||||
* @return Les produits disponibles pour ce mélange
|
||||
*/
|
||||
public Collection<Material> getAvailableMaterialsForMixId(Long recipeId, Long mixId) {
|
||||
return existsById(mixId) ? getAvailableMaterialsForMix(getById(mixId)) : getAvailableMaterialsForNewMix(recipeService.getById(recipeId));
|
||||
public Collection<Material> getAvailableMaterialsForMixId(Recipe recipe, Long mixId) {
|
||||
return existsById(mixId) ? getAvailableMaterialsForMix(getById(mixId)) : getAvailableMaterialsForNewMix(recipe);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,12 +63,12 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
* @return Les produits disponibles pour le nouveau mélange
|
||||
*/
|
||||
public Collection<Material> getAvailableMaterialsForNewMix(Recipe recipe) {
|
||||
Collection<MixType> recipeMixTypes = recipeService.getAssociatedMixesTypes(recipe);
|
||||
Collection<MixType> recipeMixTypes = recipe.getMixTypes();
|
||||
|
||||
return materialService
|
||||
.getAll()
|
||||
.stream()
|
||||
.filter(m -> !m.isMixType() || recipeMixTypes.contains(mixTypeService.getByMaterial(m).get()))
|
||||
.filter(m -> !m.isMixType() || recipeMixTypes.contains(mixTypeService.getByMaterial(m)))
|
||||
.sorted(Comparator.comparing(Material::getName))
|
||||
.sorted(Comparator.comparing(m -> m.getMaterialType().getName()))
|
||||
.collect(Collectors.toList());
|
||||
|
@ -78,77 +76,81 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
|
||||
@Transactional
|
||||
public ModelResponseBuilder create(MixCreationFormDto formDto, @NotNull Recipe recipe) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
|
||||
List<Material> materials = new ArrayList<>();
|
||||
for (String materialCode : formDto.getMaterials()) {
|
||||
Optional<Material> found = materialService.getByName(materialCode);
|
||||
if (found.isEmpty()) {
|
||||
return modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND_BY_NAME, materialCode);
|
||||
}
|
||||
|
||||
materials.add(found.get());
|
||||
}
|
||||
|
||||
Optional<MixType> optionalMixType = mixTypeService.createByName(formDto.getMixTypeName(), formDto.getMaterialType());
|
||||
if (optionalMixType.isEmpty()) return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
|
||||
MixType mixType = optionalMixType.get();
|
||||
if (recipeService.hasMixType(recipe, mixType))
|
||||
return modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, mixType.getName());
|
||||
|
||||
// Crée le mélange en premier pour avoir accès à son ID pour les autres éléments
|
||||
Mix mix = new Mix(recipe, mixType);
|
||||
|
||||
Optional<Mix> savedMix = save(mix);
|
||||
if (savedMix.isPresent()) {
|
||||
mix = savedMix.get();
|
||||
|
||||
List<MixQuantity> mixQuantities = createMixQuantities(savedMix.get(), materials, formDto.getQuantities());
|
||||
mix.setMixQuantities(mixQuantities);
|
||||
|
||||
// Retourne aucune erreur s'il la mise à jour à lieu
|
||||
if (update(mix).isPresent()) return null;
|
||||
|
||||
deleteMix(mix);
|
||||
}
|
||||
|
||||
return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
// ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
//
|
||||
// List<Material> materials = new ArrayList<>();
|
||||
// for (String materialCode : formDto.getMaterials()) {
|
||||
// Optional<Material> found = materialService.getByName(materialCode);
|
||||
// if (found.isEmpty()) {
|
||||
// return modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND_BY_NAME, materialCode);
|
||||
// }
|
||||
//
|
||||
// materials.add(found.get());
|
||||
// }
|
||||
//
|
||||
// Optional<MixType> optionalMixType = mixTypeService.createByName(formDto.getMixTypeName(), formDto.getMaterialType());
|
||||
// if (optionalMixType.isEmpty()) return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
//
|
||||
// MixType mixType = optionalMixType.get();
|
||||
// if (recipeService.hasMixType(recipe, mixType))
|
||||
// return modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, mixType.getName());
|
||||
//
|
||||
// // Crée le mélange en premier pour avoir accès à son ID pour les autres éléments
|
||||
// Mix mix = new Mix(recipe, mixType);
|
||||
//
|
||||
// Optional<Mix> savedMix = save(mix);
|
||||
// if (savedMix.isPresent()) {
|
||||
// mix = savedMix.get();
|
||||
//
|
||||
// List<MixQuantity> mixQuantities = createMixQuantities(savedMix.get(), materials, formDto.getQuantities());
|
||||
// mix.setMixQuantities(mixQuantities);
|
||||
//
|
||||
// // Retourne aucune erreur s'il la mise à jour à lieu
|
||||
// if (update(mix).isPresent()) return null;
|
||||
//
|
||||
// deleteMix(mix);
|
||||
// }
|
||||
//
|
||||
// return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ModelResponseBuilder edit(Mix mix, MixCreationFormDto formDto) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
Material material = mix.getMixType().getMaterial();
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
|
||||
List<Material> materials = new ArrayList<>();
|
||||
for (String materialCode : formDto.getMaterials()) {
|
||||
Optional<Material> found = materialService.getByName(materialCode);
|
||||
if (found.isEmpty()) {
|
||||
return modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND_BY_NAME, materialCode);
|
||||
}
|
||||
|
||||
materials.add(found.get());
|
||||
}
|
||||
|
||||
mix.getMixType().getMaterial().setMaterialType(formDto.getMaterialType());
|
||||
mix.getMixType().setName(formDto.getMixTypeName());
|
||||
material.setName(formDto.getMixTypeName());
|
||||
|
||||
List<MixQuantity> oldQuantities = mix.getMixQuantities();
|
||||
List<MixQuantity> mixQuantities = createMixQuantities(mix, materials, formDto.getQuantities());
|
||||
|
||||
// Supprime les anciens MixQuantity pour éviter les doublons et les entrées inutiles dans la base de données
|
||||
if (!mixQuantityService.deleteAll(oldQuantities)) {
|
||||
return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
}
|
||||
|
||||
mix.setMixQuantities(mixQuantities);
|
||||
if (materialService.update(material).isPresent() && update(mix).isPresent()) {
|
||||
return null;
|
||||
} else {
|
||||
return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
}
|
||||
// ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
// Material material = mix.getMixType().getMaterial();
|
||||
//
|
||||
// List<Material> materials = new ArrayList<>();
|
||||
// for (String materialCode : formDto.getMaterials()) {
|
||||
// Optional<Material> found = materialService.getByName(materialCode);
|
||||
// if (found.isEmpty()) {
|
||||
// return modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND_BY_NAME, materialCode);
|
||||
// }
|
||||
//
|
||||
// materials.add(found.get());
|
||||
// }
|
||||
//
|
||||
// mix.getMixType().getMaterial().setMaterialType(formDto.getMaterialType());
|
||||
// mix.getMixType().setName(formDto.getMixTypeName());
|
||||
// material.setName(formDto.getMixTypeName());
|
||||
//
|
||||
// List<MixQuantity> oldQuantities = mix.getMixQuantities();
|
||||
// List<MixQuantity> mixQuantities = createMixQuantities(mix, materials, formDto.getQuantities());
|
||||
//
|
||||
// // Supprime les anciens MixQuantity pour éviter les doublons et les entrées inutiles dans la base de données
|
||||
// if (!mixQuantityService.deleteAll(oldQuantities)) {
|
||||
// return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
// }
|
||||
//
|
||||
// mix.setMixQuantities(mixQuantities);
|
||||
// if (materialService.update(material).isPresent() && update(mix).isPresent()) {
|
||||
// return null;
|
||||
// } else {
|
||||
// return modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
// }
|
||||
}
|
||||
|
||||
@Deprecated(since = "1.3.0", forRemoval = true)
|
||||
|
@ -160,7 +162,7 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
@Override
|
||||
public void delete(Mix mix) {
|
||||
mixQuantityService.deleteAll(mix.getMixQuantities());
|
||||
/
|
||||
|
||||
super.delete(mix);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.model;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.ModelException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Material;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MaterialType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.MixType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.GenericService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.dao.MixTypeDao;
|
||||
|
@ -13,26 +14,35 @@ import java.util.Optional;
|
|||
@Service
|
||||
public class MixTypeService extends GenericService<MixType, MixTypeDao> {
|
||||
|
||||
private MaterialTypeService materialTypeService;
|
||||
|
||||
@Autowired
|
||||
public MixTypeService(MixTypeDao mixTypeDao, MaterialTypeService materialTypeService) {
|
||||
super(mixTypeDao);
|
||||
this.materialTypeService = materialTypeService;
|
||||
public MixTypeService(MixTypeDao mixTypeDao) {
|
||||
super(mixTypeDao, MixType.class);
|
||||
}
|
||||
|
||||
public Optional<MixType> getByName(String name) {
|
||||
return dao.findByName(name);
|
||||
/**
|
||||
* Récupère le type de mélange correspondant à un nom.
|
||||
*
|
||||
* @param name Le nom du type de mélange
|
||||
* @return Le type de mélange correspondant au nom
|
||||
*/
|
||||
public MixType getByName(String name) {
|
||||
Optional<MixType> found = dao.findByName(name);
|
||||
if (found.isEmpty()) throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, name);
|
||||
|
||||
return found.get();
|
||||
}
|
||||
|
||||
public Optional<MixType> getByMaterial(Material material) {
|
||||
return dao.findByMaterial(material);
|
||||
}
|
||||
/**
|
||||
* Récupère le type de mélange correspondant à un produit.
|
||||
*
|
||||
* @param material Le produit du type de mélange
|
||||
* @return Le type de mélange correspondant au produit
|
||||
*/
|
||||
public MixType getByMaterial(Material material) {
|
||||
Optional<MixType> found = dao.findByMaterial(material);
|
||||
if (found.isEmpty())
|
||||
throw new EntityNotFoundException(type, ModelException.IdentifierType.OTHER, MixType.IDENTIFIER_MATERIAL_NAME, material);
|
||||
|
||||
public Optional<MixType> createByName(String name, MaterialType type) {
|
||||
Material mixTypeMaterial = new Material(name, 0f, true, type);
|
||||
MixType mixType = new MixType(name, mixTypeMaterial);
|
||||
|
||||
return save(mixType);
|
||||
return found.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.model;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.FileHandler;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.ImageHandler;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.RecipeEditorFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.RecipeExplorerFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.GenericService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.files.ImagesService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.dao.RecipeDao;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -22,13 +21,15 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
private CompanyService companyService;
|
||||
private MixService mixService;
|
||||
private StepService stepService;
|
||||
private ImagesService imagesService;
|
||||
|
||||
@Autowired
|
||||
public RecipeService(RecipeDao recipeDao, CompanyService companyService, MixService mixService, StepService stepService) {
|
||||
public RecipeService(RecipeDao recipeDao, CompanyService companyService, MixService mixService, StepService stepService, ImagesService imagesService) {
|
||||
super(recipeDao, Recipe.class);
|
||||
this.companyService = companyService;
|
||||
this.mixService = mixService;
|
||||
this.stepService = stepService;
|
||||
this.imagesService = imagesService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,16 +128,21 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
* @return Une liste contenant le nom des images liées à la recette.
|
||||
*/
|
||||
public List<String> getImageFiles(Recipe recipe) {
|
||||
Long recipeId = recipe.getId();
|
||||
String name = recipe.getName();
|
||||
String fileName = String.format("%s_%s", recipeId, name);
|
||||
String imageName = getImageFileName(recipe);
|
||||
File[] allImages = imagesService.getDirectoryFile().listFiles((d, n) -> n.startsWith(imageName));
|
||||
|
||||
File imageLocation = new File(ImageHandler.IMAGES_LOCATION);
|
||||
File[] result = imageLocation.listFiles((d, n) -> n.startsWith(fileName) && n.endsWith("jpeg"));
|
||||
if (allImages == null) return new ArrayList<>();
|
||||
return Arrays.stream(allImages).map(File::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
if (result == null) return new ArrayList<>();
|
||||
// TODO test
|
||||
public int getNextImageIndex(Recipe recipe) {
|
||||
String imageName = getImageFileName(recipe);
|
||||
List<String> allImages = getImageFiles(recipe);
|
||||
List<Integer> indexes = allImages.stream().map(i -> Integer.parseInt(i.replace(imageName + "-", ""))).collect(Collectors.toList());
|
||||
int maxIndex = Collections.max(indexes);
|
||||
|
||||
return Arrays.stream(result).map(File::getName).collect(Collectors.toList());
|
||||
return maxIndex + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,32 +170,6 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les types de mélanges associés à la recette.
|
||||
*
|
||||
* @param recipe La recette dont on veut récupérer les types de mélange
|
||||
* @return Une liste contenant les types de mélanges.
|
||||
*/
|
||||
public List<MixType> getAssociatedMixesTypes(Recipe recipe) {
|
||||
return recipe
|
||||
.getMixes()
|
||||
.stream()
|
||||
.map(Mix::getMixType)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si une recette contient un mélange ayant le type de mélange spécifié.
|
||||
*
|
||||
* @param recipe La recette
|
||||
* @param mixType Le type de mélange
|
||||
* @return Si la recette contient le type de mélange
|
||||
*/
|
||||
public boolean hasMixType(Recipe recipe, MixType mixType) {
|
||||
return getAssociatedMixesTypes(recipe)
|
||||
.contains(mixType);
|
||||
}
|
||||
|
||||
private Map<Company, List<Recipe>> mappedByCompany(List<Recipe> recipes) {
|
||||
List<Company> companies = companyService.getAll();
|
||||
Map<Company, List<Recipe>> mappedRecipes = new HashMap<>();
|
||||
|
@ -236,18 +216,19 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
return update(recipe);
|
||||
}
|
||||
|
||||
private boolean removeAllFiles(Recipe recipe) {
|
||||
FileHandler fileHandler;
|
||||
for (String image : getImageFiles(recipe)) {
|
||||
fileHandler = new FileHandler(image.replace(".jpeg", ""), FileHandler.FileContext.IMAGE, FileHandler.FileExtension.JPEG);
|
||||
|
||||
if (!fileHandler.deleteFile()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
private void removeAllFiles(Recipe recipe) {
|
||||
getImageFiles(recipe).forEach(f -> imagesService.deleteImage(f));
|
||||
}
|
||||
|
||||
public String getImageFileName(Recipe recipe) {
|
||||
return String.format("%s_%s", recipe.getId(), recipe.getName());
|
||||
}
|
||||
|
||||
public String getImageFileNameWithIndex(Recipe recipe) {
|
||||
return getImageFileNameWithIndex(recipe, getNextImageIndex(recipe));
|
||||
}
|
||||
|
||||
public String getImageFileNameWithIndex(Recipe recipe, int index) {
|
||||
return String.format("%s-%s", getImageFileName(recipe), index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,91 +50,69 @@ public class InventoryController {
|
|||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Déduit les quantités utilisées de chaque matériaux présents dans le corps de la requête (JSON) de l'inventaire.
|
||||
* Le JSON dans le corps de la requête doit prendre cette forme:
|
||||
* {
|
||||
* "mixID 1": {
|
||||
* "materialID 1": "quantité 1",
|
||||
* "materialID 2": "quantité 2",
|
||||
* "materialID 3": "quantité 3"
|
||||
* },
|
||||
* "mixID 2": {
|
||||
* "materialID 1": "quantité 1"
|
||||
* },
|
||||
* ..
|
||||
* }
|
||||
* S'il y a une erreur, l'opération est annulée et aucun changement n'est fait dans l'inventaire.
|
||||
* <p>
|
||||
* Réponse de la méthode:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* - reason: Contient la raison de l'erreur (le champ fautif)
|
||||
* - success: Contient le message à affiche lors du succès de la méthode
|
||||
*
|
||||
* @param form Le JSON contenant les quantités à utiliser.
|
||||
* @return Une réponse sous forme de Map (vers Json).
|
||||
*/
|
||||
@PostMapping(value = USE_INVENTORY, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
@Transactional
|
||||
// TODO vers DTO
|
||||
// TODO + vers service
|
||||
public Map<String, Object> consumeMaterials(@RequestBody Map<String, Map<String, Float>> form) {
|
||||
JSONResponseBuilder responseBuilder = new JSONResponseBuilder();
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
|
||||
List<Mix> mixes = new ArrayList<>();
|
||||
Map<Mix, Map<Material, Float>> quantities = new HashMap<>();
|
||||
|
||||
for (String mixIDStr : form.keySet()) {
|
||||
Long mixID = Long.parseLong(mixIDStr);
|
||||
|
||||
Optional<Mix> optionalMix = mixService.getById(mixID);
|
||||
if (optionalMix.isEmpty()) {
|
||||
return responseBuilder
|
||||
.addResponseCode(ResponseCode.MIX_NOT_FOUND, mixID)
|
||||
.build();
|
||||
}
|
||||
|
||||
Mix mix = optionalMix.get();
|
||||
mixes.add(mix);
|
||||
|
||||
Map<String, Float> formMaterials = form.get(mixIDStr);
|
||||
Map<Material, Float> mixQuantities = new HashMap<>();
|
||||
|
||||
for (Material material : mix.getMixQuantities().stream().map(MixQuantity::getMaterial).collect(Collectors.toList())) {
|
||||
String materialIDAsString = String.valueOf(material.getId());
|
||||
|
||||
if (formMaterials.containsKey(materialIDAsString)) {
|
||||
Float quantityAsString = formMaterials.get(materialIDAsString);
|
||||
mixQuantities.put(material, quantityAsString);
|
||||
}
|
||||
}
|
||||
|
||||
quantities.put(mix, mixQuantities);
|
||||
}
|
||||
|
||||
for (Mix mix : mixes) {
|
||||
String errorCode = inventoryService.checkQuantities(mix, quantities.get(mix));
|
||||
if (errorCode != null) {
|
||||
String materialCode = materialService.getById(Long.parseLong(errorCode.split("-")[1])).orElse(new Material()).getName();
|
||||
|
||||
return responseBuilder
|
||||
.addResponseCode(ResponseCode.NOT_ENOUGH_MATERIAL, materialCode)
|
||||
.addAttribute(RESPONSE_REASON, errorCode)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
for (Mix mix : mixes) {
|
||||
if (!inventoryService.useMix(quantities.get(mix))) {
|
||||
return responseBuilder
|
||||
.addResponseCode(ResponseCode.ERROR_SAVING)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
return responseBuilder
|
||||
.addResponseCode(ResponseCode.SUCCESS_USING_MATERIALS)
|
||||
.build();
|
||||
// JSONResponseBuilder responseBuilder = new JSONResponseBuilder();
|
||||
//
|
||||
// List<Mix> mixes = new ArrayList<>();
|
||||
// Map<Mix, Map<Material, Float>> quantities = new HashMap<>();
|
||||
//
|
||||
// for (String mixIDStr : form.keySet()) {
|
||||
// Long mixID = Long.parseLong(mixIDStr);
|
||||
//
|
||||
// Optional<Mix> optionalMix = mixService.getById(mixID);
|
||||
// if (optionalMix.isEmpty()) {
|
||||
// return responseBuilder
|
||||
// .addResponseCode(ResponseCode.MIX_NOT_FOUND, mixID)
|
||||
// .build();
|
||||
// }
|
||||
//
|
||||
// Mix mix = optionalMix.get();
|
||||
// mixes.add(mix);
|
||||
//
|
||||
// Map<String, Float> formMaterials = form.get(mixIDStr);
|
||||
// Map<Material, Float> mixQuantities = new HashMap<>();
|
||||
//
|
||||
// for (Material material : mix.getMixQuantities().stream().map(MixQuantity::getMaterial).collect(Collectors.toList())) {
|
||||
// String materialIDAsString = String.valueOf(material.getId());
|
||||
//
|
||||
// if (formMaterials.containsKey(materialIDAsString)) {
|
||||
// Float quantityAsString = formMaterials.get(materialIDAsString);
|
||||
// mixQuantities.put(material, quantityAsString);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// quantities.put(mix, mixQuantities);
|
||||
// }
|
||||
//
|
||||
// for (Mix mix : mixes) {
|
||||
// String errorCode = inventoryService.checkQuantities(mix, quantities.get(mix));
|
||||
// if (errorCode != null) {
|
||||
// String materialCode = materialService.getById(Long.parseLong(errorCode.split("-")[1])).orElse(new Material()).getName();
|
||||
//
|
||||
// return responseBuilder
|
||||
// .addResponseCode(ResponseCode.NOT_ENOUGH_MATERIAL, materialCode)
|
||||
// .addAttribute(RESPONSE_REASON, errorCode)
|
||||
// .build();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (Mix mix : mixes) {
|
||||
// if (!inventoryService.useMix(quantities.get(mix))) {
|
||||
// return responseBuilder
|
||||
// .addResponseCode(ResponseCode.ERROR_SAVING)
|
||||
// .build();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return responseBuilder
|
||||
// .addResponseCode(ResponseCode.SUCCESS_USING_MATERIALS)
|
||||
// .build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,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.services.files.MarkdownFilesService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MixService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -22,11 +23,13 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
|||
public class OthersController {
|
||||
|
||||
private MixService mixService;
|
||||
private RecipeService recipeService;
|
||||
private MarkdownFilesService markdownService;
|
||||
|
||||
@Autowired
|
||||
public OthersController(MixService mixService, MarkdownFilesService markdownService) {
|
||||
public OthersController(MixService mixService, RecipeService recipeService, MarkdownFilesService markdownService) {
|
||||
this.mixService = mixService;
|
||||
this.recipeService = recipeService;
|
||||
this.markdownService = markdownService;
|
||||
}
|
||||
|
||||
|
@ -40,7 +43,7 @@ public class OthersController {
|
|||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(MATERIAL_SELECTOR_FRAGMENT);
|
||||
|
||||
try {
|
||||
modelResponseBuilder.addAttribute(MATERIALS, mixService.getAvailableMaterialsForMixId(recipeId, mixId));
|
||||
modelResponseBuilder.addAttribute(MATERIALS, mixService.getAvailableMaterialsForMixId(recipeService.getById(recipeId), mixId));
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, recipeId);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.files;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.ImageHandler;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.JSONResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
|
@ -9,22 +8,21 @@ import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
|||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.files.ImagesService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.utils.ControllerUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
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.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
||||
|
||||
|
@ -47,17 +45,6 @@ public class ImageFilesController {
|
|||
return new ResponseEntity<>(imagesService.readImage(image), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche la page pour ajouter une image pour une recette.
|
||||
* Cette méthode requiert l'identifiant de la recette dans l'URL.
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - id: Contient l'identifiant de la recette
|
||||
*
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @param id L'identifiant de la recette
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@GetMapping(ADD_IMAGE_SPECIFIC)
|
||||
public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
|
||||
return new ModelResponseBuilder(model)
|
||||
|
@ -66,94 +53,32 @@ public class ImageFilesController {
|
|||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à l'utilisateur d'uploader une image.
|
||||
* <p>
|
||||
* L'upload échouera si:
|
||||
* - L'utilisateur n'est pas autorisé à exécuter cette action.
|
||||
* - La recette n'existe pas
|
||||
* - Une erreur est survenue lors de la création du fichier de l'image
|
||||
* - Une erreur est survenue lors du transfert de l'image vers le fichier
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* - recipeCode: Contient la couleur de la recette
|
||||
* - id: Contient l'identifiant de la recette
|
||||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param id L'identifiant de la recette
|
||||
* @param image L'image uploadée
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@PostMapping(ADD_IMAGE)
|
||||
public ModelAndView addImage(Long id, MultipartFile image) throws IOException {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(ControllerUtils.redirect(EDITOR_RECIPE_SPECIFIC.replace("{id}", String.valueOf(id))));
|
||||
|
||||
// Vérifie que le fichier est bien une image
|
||||
if (ImageIO.read(image.getInputStream()) == null) {
|
||||
return getPage(modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.FILE_NOT_IMAGE)
|
||||
.build(), id);
|
||||
}
|
||||
|
||||
Optional<Recipe> optionalRecipe = recipeService.getById(id);
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
return getPage(modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id)
|
||||
.build(), id);
|
||||
}
|
||||
|
||||
Recipe recipe = optionalRecipe.get();
|
||||
ImageHandler imageHandler = new ImageHandler(recipe, recipeService);
|
||||
if (!imageHandler.createFile()) {
|
||||
return getPage(modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.ERROR_SAVING_IMAGE)
|
||||
.build(), id);
|
||||
}
|
||||
|
||||
modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.RECIPE_CODE, recipe.getName())
|
||||
.addResponseData(ResponseDataType.RECIPE_ID, recipe.getId());
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_RECIPE_SPECIFIC, id);
|
||||
|
||||
try {
|
||||
// Si je n'utilise pas le path, il cherche un fichier dans les tmp ?
|
||||
image.transferTo(new File(imageHandler.getFile().getAbsolutePath()));
|
||||
if (imagesService.isImage(image.getInputStream())) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.FILE_NOT_IMAGE);
|
||||
} else {
|
||||
Recipe recipe = recipeService.getById(id);
|
||||
|
||||
return modelResponseBuilder.build();
|
||||
} catch (IOException e) {
|
||||
ColorRecipesExplorerApplication.LOGGER.error("Erreur inconnue lors de la création d'une image", e);
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_IMAGE);
|
||||
|
||||
return getPage(modelResponseBuilder.build(), id);
|
||||
if (imagesService.writeMultipartImage(image, recipeService.getImageFileNameWithIndex(recipe)))
|
||||
return modelResponseBuilder.build();
|
||||
else modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_IMAGE);
|
||||
}
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
return getPage(modelResponseBuilder.build(), id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à l'utilisateur de supprimer une image.
|
||||
* <p>
|
||||
* La suppression échouera si:
|
||||
* - L'utilisateur n'est pas autorisé à exécuter cette action
|
||||
* - Une erreur est survenue lors de la suppression du fichier
|
||||
* <p>
|
||||
* Réponse de la méthode:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param form Le formulaire contenant les informations sur l'opération
|
||||
* @return La réponse sous forme de Map (pour y accéder en Json)
|
||||
*/
|
||||
@PostMapping(value = DELETE_IMAGE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public Map<String, Object> deleteImage(@RequestBody Map<String, String> form) {
|
||||
JSONResponseBuilder responseBuilder = new JSONResponseBuilder();
|
||||
public Map<String, Object> deleteImage(String image) {
|
||||
imagesService.deleteImage(image);
|
||||
|
||||
ImageHandler imageHandler = new ImageHandler(form.get("image"), recipeService);
|
||||
if (!imageHandler.deleteFile()) {
|
||||
responseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_IMAGE);
|
||||
}
|
||||
|
||||
return responseBuilder.build();
|
||||
return new JSONResponseBuilder().build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.files;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.FileHandler;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Material;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.files.SimdutService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CLOSE_TAB;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.SIMDUT_FILES;
|
||||
|
@ -22,41 +21,38 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.SIMDUT_FILES
|
|||
@Controller
|
||||
public class SIMDUTFilesController {
|
||||
|
||||
private MaterialService materialService;
|
||||
private SimdutService simdutService;
|
||||
|
||||
@Autowired
|
||||
public SIMDUTFilesController(MaterialService materialService) {
|
||||
this.materialService = materialService;
|
||||
public SIMDUTFilesController(SimdutService simdutService) {
|
||||
this.simdutService = simdutService;
|
||||
}
|
||||
|
||||
@GetMapping(SIMDUT_FILES)
|
||||
public ResponseEntity<byte[]> getFile(HttpServletRequest request, @PathVariable Long id) {
|
||||
Optional<Material> optionalMaterial = materialService.getById(id);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
if (optionalMaterial.isEmpty()) {
|
||||
headers.add("Location", request.getHeader("referer"));
|
||||
return new ResponseEntity<>(headers, HttpStatus.FOUND);
|
||||
}
|
||||
|
||||
FileHandler fileHandler = new FileHandler(String.format("%s_%s", id, optionalMaterial.get().getName()), FileHandler.FileContext.SIMDUT, FileHandler.FileExtension.PDF);
|
||||
if (!fileHandler.isValid()) {
|
||||
try {
|
||||
if (simdutService.simdutExistsForMaterialId(id)) {
|
||||
byte[] simdutContent = simdutService.readSimdutForMaterialId(id);
|
||||
headers.setContentType(MediaType.APPLICATION_PDF);
|
||||
return new ResponseEntity<>(simdutContent, headers, HttpStatus.OK);
|
||||
} else {
|
||||
headers.add("Location", request.getHeader("referer"));
|
||||
}
|
||||
} catch (EntityNotFoundException ex) {
|
||||
headers.add("Location", "/" + CLOSE_TAB);
|
||||
return new ResponseEntity<>(headers, HttpStatus.FOUND);
|
||||
}
|
||||
|
||||
byte[] fileContent = fileHandler.readFile();
|
||||
headers.setContentType(MediaType.APPLICATION_PDF);
|
||||
return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);
|
||||
return new ResponseEntity<>(headers, HttpStatus.FOUND);
|
||||
}
|
||||
|
||||
@PostMapping(SIMDUT_FILES)
|
||||
public ResponseEntity<Void> getFile(@PathVariable Long id) {
|
||||
Optional<Material> optionalMaterial = materialService.getById(id);
|
||||
if (optionalMaterial.isEmpty()) return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
|
||||
|
||||
FileHandler fileHandler = new FileHandler(String.format("%s_%s", id, optionalMaterial.get().getName()), FileHandler.FileContext.SIMDUT, FileHandler.FileExtension.PDF);
|
||||
if (!fileHandler.isValid()) return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
|
||||
return ResponseEntity.status(HttpStatus.FOUND).build();
|
||||
try {
|
||||
return ResponseEntity.status(simdutService.simdutExistsForMaterialId(id) ? HttpStatus.FOUND : HttpStatus.NOT_FOUND).build();
|
||||
} catch (EntityNotFoundException ex) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.files;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.xlsx.XlsxExporter;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.files.XlsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
@ -14,76 +12,50 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.ALL_RECIPES_XLS;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.RECIPE_XLS;
|
||||
|
||||
// TODO Une grande partie du code de ce controlleur devrait se trouver dans un service
|
||||
@Controller
|
||||
public class XlsExporterController {
|
||||
|
||||
private RecipeService recipeService;
|
||||
private XlsService xlsService;
|
||||
|
||||
@Autowired
|
||||
public XlsExporterController(RecipeService recipeService) {
|
||||
this.recipeService = recipeService;
|
||||
public XlsExporterController(XlsService xlsService) {
|
||||
this.xlsService = xlsService;
|
||||
}
|
||||
|
||||
@GetMapping(RECIPE_XLS)
|
||||
public ResponseEntity<byte[]> getXlsForRecipe(HttpServletRequest request, @PathVariable Long id) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
Optional<Recipe> optionalRecipe = recipeService.getById(id);
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
try {
|
||||
byte[] xlsContent = xlsService.generateXlsForRecipeId(id);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentLength(xlsContent.length)
|
||||
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
|
||||
.body(xlsContent);
|
||||
} catch (EntityNotFoundException ex) {
|
||||
headers.add(HttpHeaders.LOCATION, request.getHeader("referer"));
|
||||
return new ResponseEntity<>(headers, HttpStatus.FOUND);
|
||||
}
|
||||
|
||||
byte[] recipeXLS = new XlsxExporter().generate(optionalRecipe.get());
|
||||
if (recipeXLS.length <= 0) return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentLength(recipeXLS.length)
|
||||
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
|
||||
.body(recipeXLS);
|
||||
}
|
||||
|
||||
@GetMapping(value = ALL_RECIPES_XLS, produces = "application/zip")
|
||||
public ResponseEntity<byte[]> getAllXls() throws IOException {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
ColorRecipesExplorerApplication.LOGGER.info("Exportation de toutes les couleurs en XLS");
|
||||
|
||||
ByteArrayOutputStream byteOS = new ByteArrayOutputStream();
|
||||
ZipOutputStream out = new ZipOutputStream(byteOS);
|
||||
|
||||
Collection<Recipe> recipes = recipeService.getAll();
|
||||
for (Recipe recipe : recipes) {
|
||||
byte[] recipeXLS = new XlsxExporter().generate(recipe);
|
||||
if (recipeXLS.length <= 0) return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
|
||||
out.putNextEntry(new ZipEntry(String.format("%s_%s.xlsx", recipe.getCompany().getName(), recipe.getName())));
|
||||
out.write(recipeXLS, 0, recipeXLS.length);
|
||||
out.closeEntry();
|
||||
}
|
||||
|
||||
out.close();
|
||||
|
||||
byte[] zipContent = byteOS.toByteArray();
|
||||
byteOS.close();
|
||||
byte[] allXlsContent = xlsService.generateXlsForAllRecipes();
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentLength(zipContent.length)
|
||||
.contentLength(allXlsContent.length)
|
||||
.contentType(MediaType.parseMediaType("application/zip"))
|
||||
.body(zipContent);
|
||||
.body(allXlsContent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ public class CompanyRemoverController {
|
|||
try {
|
||||
companyService.deleteById(id);
|
||||
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_COMPANY, companyService.getById(id));
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_COMPANY, companyService.getById(id).getName());
|
||||
} catch (EntityLinkedException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_LINKED, companyService.getById(id));
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_LINKED, companyService.getById(id).getName());
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_NOT_FOUND, id);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.removers;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityLinkedException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
|
@ -28,12 +30,6 @@ public class MaterialRemoverController {
|
|||
this.materialService = materialService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche la page de suppression des produits
|
||||
*
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@GetMapping(REMOVER_MATERIAL)
|
||||
public ModelAndView getPage(ModelAndView model) {
|
||||
return new ModelResponseBuilder(model)
|
||||
|
@ -42,45 +38,20 @@ public class MaterialRemoverController {
|
|||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à l'utilisateur de supprimer un produit.
|
||||
* Cette méthode requiert l'identifiant du produit dans l'URL.
|
||||
* <p>
|
||||
* La suppression échouera si:
|
||||
* - L'utilisateur n'est pas autorisé à exécuter cette action
|
||||
* - Le produit n'existe pas
|
||||
* - Le produit est lié à d'autres mélanges
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* - materialCode: Contient le code de produit du produit supprimé
|
||||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param id L'identifiant du produit à supprimer
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@PostMapping(REMOVER_MATERIAL_SPECIFIC)
|
||||
public ModelAndView removeMaterial(@PathVariable Long id) {
|
||||
ModelResponseBuilder responseBuilder = new ModelResponseBuilder("");
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
|
||||
Optional<Material> optionalMaterial = materialService.getById(id);
|
||||
if (optionalMaterial.isEmpty()) {
|
||||
responseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, id);
|
||||
} else {
|
||||
Material material = optionalMaterial.get();
|
||||
try {
|
||||
materialService.deleteById(id);
|
||||
|
||||
if (materialService.deleteIfNotLinked(material)) {
|
||||
responseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_MATERIAL, material.getName());
|
||||
|
||||
if (!materialService.removeSimdut(material)) {
|
||||
responseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_SIMDUT);
|
||||
}
|
||||
} else {
|
||||
responseBuilder.addResponseCode(ResponseCode.MATERIAL_LINKED, material.getName());
|
||||
}
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_MATERIAL, materialService.getById(id).getName());
|
||||
} catch (EntityLinkedException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_LINKED, materialService.getById(id).getName());
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
return getPage(responseBuilder.build());
|
||||
return getPage(modelResponseBuilder.build());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.removers;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityLinkedException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
|
@ -38,21 +40,18 @@ public class MaterialTypeRemoverController {
|
|||
|
||||
@PostMapping(REMOVER_MATERIAL_TYPE_SPECIFIC)
|
||||
public ModelAndView removeMaterialType(@PathVariable Long id) {
|
||||
ModelResponseBuilder responseBuilder = new ModelResponseBuilder("");
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
|
||||
Optional<MaterialType> optionalMaterialType = materialTypeService.getById(id);
|
||||
if (optionalMaterialType.isEmpty()) {
|
||||
responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_NOT_FOUND, id);
|
||||
} else {
|
||||
MaterialType materialType = optionalMaterialType.get();
|
||||
try {
|
||||
materialTypeService.deleteById(id);
|
||||
|
||||
if (materialTypeService.deleteIfNotLinked(materialType)) {
|
||||
responseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_MATERIAL_TYPE, materialType.getName());
|
||||
} else {
|
||||
responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_LINKED, materialType.getName());
|
||||
}
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_MATERIAL_TYPE, materialTypeService.getById(id).getName());
|
||||
} catch (EntityLinkedException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_LINKED, materialTypeService.getById(id).getName());
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
return getPage(responseBuilder.build());
|
||||
return getPage(modelResponseBuilder.build());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.removers;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
|
@ -25,59 +26,26 @@ public class RecipeRemoverController {
|
|||
this.recipeService = recipeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche la liste de toutes les recettes.
|
||||
*
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@GetMapping(REMOVER_RECIPE)
|
||||
public ModelAndView listRecipes(ModelAndView model) {
|
||||
public ModelAndView getPage(ModelAndView model) {
|
||||
return new ModelResponseBuilder(model)
|
||||
.withView(REMOVER_RECIPE)
|
||||
.addResponseData(ResponseDataType.RECIPE_MAP, recipeService.getRecipesByCompany())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à l'utilisateur de supprimer une recette.
|
||||
* Cette méthode requiert l'identifiant de la recette dans l'URL.
|
||||
* <p>
|
||||
* La suppression échouera si:
|
||||
* - L'utilisateur n'est pas autorisé à exécuter cette action
|
||||
* - La recette n'existe pas
|
||||
* - Une erreur est survenue lors de la suppression dans la base de données
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* - recipeCode: Contient la couleur de la recette
|
||||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param id L'identifiant de la recette
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@PostMapping(REMOVER_RECIPE_SPECIFIC)
|
||||
public ModelAndView removeRecipe(@PathVariable Long id) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder("");
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
|
||||
Optional<Recipe> optionalRecipe = recipeService.getById(id);
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
return listRecipes(
|
||||
modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id)
|
||||
.build());
|
||||
try {
|
||||
recipeService.deleteById(id);
|
||||
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_RECIPE, recipeService.getById(id).getName());
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
Recipe recipe = optionalRecipe.get();
|
||||
if (!recipeService.deleteRecipe(recipe)) {
|
||||
return listRecipes(
|
||||
modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.ERROR_SAVING)
|
||||
.build());
|
||||
}
|
||||
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_RECIPE, recipe.getName());
|
||||
return listRecipes(modelResponseBuilder.build());
|
||||
return getPage(modelResponseBuilder.build());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue