Merge branch 'drop-thymeleaf' into 'master'

Drop thymeleaf

See merge request color-recipes-explorer/backend!15
This commit is contained in:
William Nolin 2021-03-16 20:43:29 +00:00
commit 376d244f29
189 changed files with 380 additions and 44221 deletions

View File

@ -1,46 +0,0 @@
param (
[string]$WorkDir = "./workdir",
[string]$BackupPath = "./backup",
[boolean]$OverWrite = $False
)
Write-Host "Démarrage de la sauvegarde..."
if (!(Test-Path -Path $WorkDir))
{
Write-Host "Le dossier de travail ($WorkDir) n'existe pas."
exit
}
if (!(Test-Path -Path $BackupPath))
{
Write-Host "Création du dossier des sauvegardes. ($BackupPath)"
New-Item -ItemType directory -Path $BackupPath | Out-Null
}
Write-Host "Début de la compression..."
$BackupFile = "$BackupPath/backup_$( Get-Date -f yyyyMMdd-HHmm ).zip"
$CompressArgs = @{
'Path' = $WorkDir
'DestinationPath' = $BackupFile
'Update' = $OverWrite
}
try
{
Compress-Archive @CompressArgs
Write-Host "Sauvegarde réussie! ($BackupFile)"
}
catch [System.IO.IOException]
{
Write-Output "Une erreur est survenue lors de la sauvegarde:"
if ($_.FullyQualifiedErrorId -like "ArchiveFileExists*")
{
Write-Host "L'archive de sauvegarde '$BackupFile' existe déjà. Ajoutez l'argument '-OverWrite `$true' pour écraser l'archive."
}
else
{
Write-Host $_
}
}

View File

@ -5,7 +5,6 @@ plugins {
id("org.jetbrains.kotlin.jvm") version "1.4.30"
id("org.jetbrains.dokka") version "1.4.20"
id("com.leobia.gradle.sassjavacompiler") version "0.2.1"
id("io.freefair.lombok") version "5.2.1"
id("org.springframework.boot") version "2.3.4.RELEASE"
id("org.jetbrains.kotlin.plugin.spring") version "1.4.30"
id("org.jetbrains.kotlin.plugin.jpa") version "1.4.30"
@ -29,13 +28,10 @@ dependencies {
implementation("io.jsonwebtoken:jjwt:0.9.1")
implementation("org.apache.poi:poi-ooxml:4.1.0")
implementation("org.apache.pdfbox:pdfbox:2.0.4")
implementation("com.atlassian.commonmark:commonmark:0.13.1")
implementation("commons-io:commons-io:2.6")
implementation("dev.fyloz.colorrecipesexplorer:database-manager:1.1.0")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.3.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-jdbc:2.3.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:2.3.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-web:2.3.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-validation:2.3.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-security:2.3.4.RELEASE")
@ -55,8 +51,6 @@ dependencies {
runtimeOnly("mysql:mysql-connector-java:8.0.22")
runtimeOnly("org.postgresql:postgresql:42.2.16")
runtimeOnly("com.microsoft.sqlserver:mssql-jdbc:9.2.1.jre11")
compileOnly("org.projectlombok:lombok:1.18.10")
}
java {

View File

@ -1,2 +0,0 @@
# This file is generated by the 'io.freefair.lombok' Gradle plugin
config.stopBubbling = true

View File

@ -1,32 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.config;
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialService;
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialTypeService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class InitialDataLoader implements ApplicationListener<ApplicationReadyEvent> {
private final MaterialTypeService materialTypeService;
private final MaterialTypeProperties materialTypeProperties;
@Autowired
public InitialDataLoader(MaterialTypeService materialTypeService, MaterialTypeProperties materialTypeProperties) {
this.materialTypeService = materialTypeService;
this.materialTypeProperties = materialTypeProperties;
}
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
materialTypeService.saveSystemTypes(materialTypeProperties.getSystemTypes());
}
}

View File

@ -1,51 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.Locale;
@Configuration
public class LocaleConfiguration implements WebMvcConfigurer {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:lang/messages", "classpath:lang/responses");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.FRENCH);
return localeResolver;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
@Bean
public LocalValidatorFactoryBean validator(MessageSource messageSource) {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource);
return bean;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}

View File

@ -1,22 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.config;
import org.slf4j.Logger;
import org.springframework.context.MessageSource;
public class Preferences {
public static Logger logger;
public static MessageSource messageSource;
public static boolean urlUsePort;
public static boolean urlUseHttps;
public static String uploadDirectory;
public static String passwordsFileName;
public static String baseMaterialTypeName;
}

View File

@ -1,88 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.config;
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CREProperties;
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties;
import dev.fyloz.trial.colorrecipesexplorer.service.PasswordService;
import dev.fyloz.trial.colorrecipesexplorer.service.files.FilesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 java.io.IOException;
import java.util.List;
@Configuration
public class SpringConfiguration {
private FilesService filesService;
private MessageSource messageSource;
private CREProperties creProperties;
private MaterialTypeProperties materialTypeProperties;
@Autowired
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 Logger getLogger() {
return LoggerFactory.getLogger(ColorRecipesExplorerApplication.class);
}
@Bean
public void setPreferences() {
Preferences.urlUsePort = creProperties.isUrlUsePort();
Preferences.urlUseHttps = creProperties.isUrlUseHttps();
Preferences.uploadDirectory = creProperties.getUploadDirectory();
Preferences.passwordsFileName = creProperties.getPasswordFile();
Preferences.logger = getLogger();
Preferences.messageSource = messageSource;
Preferences.baseMaterialTypeName = materialTypeProperties.getBaseName();
}
@Bean
public void initializePasswords() {
Logger logger = Preferences.logger;
String filePath = filesService.getPath(Preferences.passwordsFileName);
logger.info("Le fichier des utilisateurs se situe à: " + filesService.getFile(filePath).getAbsolutePath());
try {
if (!filesService.exists(filePath)) filesService.create(filePath);
List<String> fileContent = filesService.readAsStrings(filePath);
if (fileContent.size() < 1) {
logger.warn("Aucun mot de passe trouvé. Il sera impossible d'utiliser certaines fonctionnalités de l'application.");
}
for (String line : fileContent) {
PasswordService.addPassword(line);
}
} 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és de l'application.");
}
}
}

View File

@ -1,19 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.config.properties;
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 urlUseHttps;
private boolean urlUsePort;
}

View File

@ -1,14 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import lombok.Getter;
@Getter
public class CannotDeleteDefaultMaterialTypeException extends RuntimeException {
private MaterialType materialType;
public CannotDeleteDefaultMaterialTypeException(MaterialType materialType) {
this.materialType = materialType;
}
}

View File

@ -1,14 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MaterialTypeEditorDto;
import lombok.Getter;
@Getter
public class CannotEditDefaultMaterialTypeException extends RuntimeException {
private MaterialTypeEditorDto materialType;
public CannotEditDefaultMaterialTypeException(MaterialTypeEditorDto materialType) {
this.materialType = materialType;
}
}

View File

@ -1,12 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
public class SimdutException extends RuntimeException {
private Material material;
public SimdutException(Material material) {
this.material = material;
}
}

View File

@ -1,25 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import lombok.Getter;
@Getter
public class TooLowQuantityException extends RuntimeException {
private Long mixId;
private Material material;
private Float storedQuantity;
private Float requestQuantity;
private String response;
public TooLowQuantityException(Long mixId, Material material, Float storedQuantity, Float requestQuantity) {
this.mixId = mixId;
this.material = material;
this.storedQuantity = storedQuantity;
this.requestQuantity = requestQuantity;
response = String.format("%s_%s", mixId, material.getId());
}
}

View File

@ -1,37 +0,0 @@
//package dev.fyloz.trial.colorrecipesexplorer.exception.model;
//
//import dev.fyloz.trial.colorrecipesexplorer.model.IModel;
//import lombok.Getter;
//import lombok.NonNull;
//import org.springframework.http.HttpStatus;
//import org.springframework.web.bind.annotation.ResponseStatus;
//
//@Getter
//@ResponseStatus(HttpStatus.CONFLICT)
//public class EntityAlreadyExistsException extends ModelException {
//
// @NonNull
// private IdentifierType identifierType;
//
// private String identifierName;
//
// @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;
// this.requestedId = requestedId;
// }
//
// public EntityAlreadyExistsException(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;
// }
//}

View File

@ -1,13 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception.model;
import dev.fyloz.trial.colorrecipesexplorer.model.Model;
/**
* Représente une exception qui sera lancée lorsqu'un objet du modèle qui est lié à un autre entité doit être supprimé
*/
public class EntityLinkedException extends ModelException {
public EntityLinkedException(Class<? extends Model> type) {
super(type);
}
}

View File

@ -1,39 +0,0 @@
//package dev.fyloz.trial.colorrecipesexplorer.exception.model;
//
//import dev.fyloz.trial.colorrecipesexplorer.model.IModel;
//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 {
//
// /**
// * Le type d'identifiant utilisé
// */
// private IdentifierType identifierType;
//
// /**
// * Le nom de l'identifiant utilisé (optionnel)
// */
// private String identifierName;
//
// /**
// * La valeur de l'identifiant
// */
// private Object requestedId;
//
// public EntityNotFoundException(Class<? extends IModel> type, IdentifierType identifierType, Object requestedId) {
// super(type);
// this.identifierType = identifierType;
// this.requestedId = requestedId;
// }
//
// 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;
// }
//}

View File

@ -1,38 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception.model;
import dev.fyloz.trial.colorrecipesexplorer.model.Model;
/**
* Représente une exception qui sera déclenchée lors des opérations sur le modèle.
*/
public class ModelException extends RuntimeException {
/**
* Le type de modèle qui est sujet à l'exception
*/
protected Class<? extends Model> type;
public ModelException(Class<? extends Model> type) {
this.type = type;
}
public Class<? extends Model> getType() {
return type;
}
public enum IdentifierType {
ID("id"),
NAME("name"),
OTHER("");
private String name;
IdentifierType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}

View File

@ -1,15 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception.model;
import dev.fyloz.trial.colorrecipesexplorer.model.Model;
public class NullIdentifierException extends ModelException {
public NullIdentifierException(Class<? extends Model> type) {
super(type);
}
@Override
public String getMessage() {
return String.format("Un modèle de type '%s' avait un identifiant nécessaire null", type.getSimpleName());
}
}

View File

@ -1,42 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model.dto;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MaterialTypeEditorDto {
private Long id;
private String oldName;
private String name;
private String oldPrefix;
private String prefix;
private boolean usePercentages;
public MaterialTypeEditorDto(MaterialType materialType) {
this.id = materialType.getId();
this.oldName = materialType.getName();
this.name = materialType.getName();
this.oldPrefix = materialType.getPrefix();
this.prefix = materialType.getPrefix();
this.usePercentages = materialType.getUsePercentages();
}
public MaterialType getMaterialType() {
return new MaterialType(id, name, prefix, usePercentages, false);
}
public MaterialType getOldMaterialType() {
return new MaterialType(id, oldName, oldPrefix, usePercentages, false);
}
}

View File

@ -1,26 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model.dto;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
public class MixFormDto {
private Recipe recipe;
private String oldMixTypeName;
private String mixTypeName;
private MaterialType materialType;
private List<String> materials;
private List<Float> quantities;
}

View File

@ -1,39 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model.dto;
import dev.fyloz.trial.colorrecipesexplorer.model.Company;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import lombok.Data;
import java.time.LocalDate;
import java.util.List;
@Data
public class RecipeEditorFormDto {
private Long id;
private String name;
private Company company;
private String description;
private Integer sample;
private LocalDate approbationDate;
private String remark;
private String note;
private List<String> step;
public Recipe getRecipe() {
return new Recipe(id, name, company, description, "ffffff", (byte) 0, sample, approbationDate, remark, note);
}
public Recipe update(Recipe original) {
return new Recipe(original.getId(), name, company, description, "ffffff", (byte) 0, sample, approbationDate, remark, note);
}
}

View File

@ -1,14 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model.dto;
import lombok.Data;
import java.util.Map;
@Data
public class RecipeExplorerFormDto {
private Long recipeId;
private Map<Long, String> locations;
private String note;
}

View File

@ -1,29 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.NamedModel;
import dev.fyloz.trial.colorrecipesexplorer.repository.NamedJpaRepository;
abstract public class AbstractJavaNamedService<E extends NamedModel, R extends NamedJpaRepository<E>> extends AbstractJavaService<E, R> {
public AbstractJavaNamedService(Class<E> type) {
super(type);
}
public boolean existsByName(String name) {
return repository.existsByName(name);
}
public E getByName(String name) {
E found = repository.findByName(name);
if (found == null) throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, name);
return found;
}
public void deleteByName(String name) {
repository.deleteByName(name);
}
}

View File

@ -1,157 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.NullIdentifierException;
import dev.fyloz.trial.colorrecipesexplorer.model.Model;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public abstract class AbstractJavaService<E extends Model, R extends JpaRepository<E, Long>> implements IGenericJavaService<E> {
protected Logger logger = Preferences.logger;
protected R repository;
protected Class<E> type;
public AbstractJavaService(Class<E> type) {
this.type = type;
}
public R getRepository() {
return repository;
}
@Override
public boolean existsById(Long id) {
return repository.existsById(id);
}
/**
* Vérifie si une entité correspondant à un identifiant existe.
* <p>
* Méthode pour la compatibilité avec les services Kotlin.
*
* @param id L'identifiant de l'entité
* @return Si un entité correspondant à l'identifiant existe
*/
public boolean existsById(long id) {
return existsById(Long.valueOf(id));
}
/**
* Méthode utilitaire pour wrapper les entités nullables dans un Optional.
* <p>
* Méthode pour la compatibilité avec les repository Kotlin.
*
* @param entity L'entité nullable
* @return Un optional wrapper l'entité donnée
*/
protected Optional<E> findOptional(@Nullable E entity) {
return Optional.ofNullable(entity);
}
@Override
public E getById(Long id) {
Optional<E> found = repository.findById(id);
if (found.isEmpty()) throw new EntityNotFoundException(type, EntityNotFoundException.IdentifierType.ID, id);
return found.get();
}
/**
* Récupère l'entité de type T correspondant à un identifiant.
* <p>
* Méthode pour la compatibilité avec les services Kotlin.
*
* @param id L'identifiant de l'entité
* @return L'entité correspondant à l'identifiant
*/
public E getById(long id) {
return getById(Long.valueOf(id));
}
@Override
public List<E> getAll() {
return repository.findAll();
}
@Override
public E save(@NotNull E entity) {
if (entity.getId() != null && existsById(entity.getId()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.ID, entity.getId());
return repository.save(entity);
}
@Override
@Transactional
public Collection<E> saveAll(@NotNull Collection<E> entities) {
return entities
.stream()
.map(this::save)
.collect(Collectors.toList());
}
@Override
public E update(@NotNull E entity) {
if (entity.getId() == null) throw new NullIdentifierException(type);
if (!existsById(entity.getId()))
throw new EntityNotFoundException(type, ModelException.IdentifierType.ID, entity.getId());
return repository.save(entity);
}
@Override
public void delete(@NotNull E entity) {
repository.delete(entity);
}
@Override
public void deleteById(Long id) {
delete(getById(id));
}
/**
* Supprime une entité correspondant à l'identifiant.
* <p>
* Méthode pour la compatibilité avec les services Kotlin.
*
* @param id L'identifiant de l'entité à supprimer
*/
public void deleteById(long id) {
deleteById(Long.valueOf(id));
}
@Override
public void deleteAll(Collection<E> entities) {
repository.deleteAll(entities);
}
/**
* Transforme un objet en Json.
*
* @param obj L'objet à transformer
* @return L'objet sous forme de Json.
*/
public String asJson(Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
Preferences.logger.error("Une erreur est survenue lors de la transformation d'un objet en Json", e);
return null;
}
}
}

View File

@ -1,77 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service;
import dev.fyloz.trial.colorrecipesexplorer.model.Model;
import java.util.Collection;
import java.util.List;
public interface IGenericJavaService<T extends Model> {
/**
* Vérifie si une entité correspondant à un identifiant existe.
*
* @param id L'identifiant de l'entité
* @return Si un entité correspondant à l'identifiant existe
*/
boolean existsById(Long id);
/**
* Récupère toutes les entités de type T.
*
* @return Toutes les entités de type T
*/
List<T> getAll();
/**
* Récupère l'entité de type T correspondant à un identifiant.
*
* @param id L'identifiant de l'entité
* @return L'entité correspondant à l'identifiant
*/
T getById(Long id);
/**
* Crée une entité.
*
* @param entity L'entité à créer
* @return L'entité créée
*/
T save(T entity);
/**
* Crée plusieurs entités.
*
* @param entities Les entités à créer
* @return Les entités créées
*/
Collection<T> saveAll(Collection<T> entities);
/**
* Met à jour une entité dans le stockage.
*
* @param entity L'entité à mettre à jour
* @return L'entité mise à jour
*/
T update(T entity);
/**
* Supprime une entité.
*
* @param entity L'entité à supprimer
*/
void delete(T entity);
/**
* Supprime une entité correspondant à l'identifiant.
*
* @param id L'identifiant de l'entité à supprimer
*/
void deleteById(Long id);
/**
* Supprime plusieurs entités.
*
* @param entities Les entités à supprimer
*/
void deleteAll(Collection<T> entities);
}

View File

@ -1,17 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service;
import java.util.ArrayList;
import java.util.List;
public class PasswordService {
private static List<String> passwords = new ArrayList<>();
public static boolean isValid(String password) {
return passwords.contains(password);
}
public static void addPassword(String password) {
passwords.add(password);
}
}

View File

@ -1,155 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
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 {
private ResourceLoader resources;
@Autowired
public FilesService(ResourceLoader resources) {
this.resources = resources;
}
/**
* Lit un fichier dans le dossier resources.
*
* @param path Le chemin vers la fichier (sans classpath:, depuis le dossier resources)
* @return Le contenu du fichier
*/
public String readResource(String path) {
String fullPath = String.format("classpath:%s", path);
try (InputStream stream = resources.getResource(fullPath).getInputStream()) {
return readInputStreamAsString(stream);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* Lit un InputStream et le transforme en String
*
* @param input L'InputStream
* @return Le InputStream transformé en String
* @throws IOException La transformation vers un String a échoué
*/
public String readInputStreamAsString(InputStream input) throws IOException {
byte[] data = FileCopyUtils.copyToByteArray(input);
return new String(data, StandardCharsets.UTF_8);
}
/**
* Récupère le contenu d'un fichier dans un tableau de Byte.
*
* @param path Le chemin vers le fichier
* @return Le contenu du fichier dans un tableau de Byte
* @throws IOException La lecture du fichier a échoué
*/
public byte[] readAsBytes(String path) throws IOException {
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> readAsStrings(String path) throws IOException {
return Files.readAllLines(Paths.get(path));
}
/**
* Écrit un fichier Multipart sur le disque.
*
* @param multipartFile Le fichier à écrire
* @param path Le chemin vers le fichier
* @return Si le fichier a bien été créé
*/
public boolean write(MultipartFile multipartFile, String path) {
if (multipartFile.getSize() <= 0) return true;
try {
File file = create(path);
multipartFile.transferTo(file.toPath());
return true;
} catch (IOException ex) {
Preferences.logger.error("Impossible d'écrire un fichier Multipart: " + ex.getMessage());
return false;
}
}
/**
* Crée un fichier sur le disque.
*
* @param path Le chemin vers le fichier
* @return Le fichier créé
* @throws IOException La création du fichier échoue
*/
public File create(String path) throws IOException {
File file = getFile(path);
try {
if (!file.exists() || file.isDirectory()) {
Files.createDirectories(file.getParentFile().toPath());
Files.createFile(file.toPath());
}
return file;
} catch (IOException ex) {
throw new RuntimeException("Impossible de créer un fichier: ", ex);
}
}
/**
* Supprime un fichier sur le disque.
*
* @param path Le chemin vers le fichier
*/
public void delete(String path) {
File file = getFile(path);
try {
if (file.exists() && !file.isDirectory()) Files.delete(file.toPath());
} catch (IOException ex) {
throw new RuntimeException("Impossible de supprimer un fichier: " + ex.getMessage());
}
}
/**
* Vérifie si un fichier existe sur le disque.
*
* @param path Le chemin vers le fichier
* @return Si le fichier existe
*/
public boolean exists(String path) {
File file = getFile(path);
return file.exists() && !file.isDirectory();
}
public File getFile(String path) {
return new File(path);
}
public String getPath(String fileName) {
return String.format("%s/%s", Preferences.uploadDirectory, fileName);
}
}

View File

@ -1,80 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
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 {
private static final String IMAGES_DIRECTORY = "images";
private FilesService filesService;
@Autowired
public ImagesService(FilesService filesService) {
this.filesService = filesService;
}
/**
* Lit une image.
*
* @param name Le nom de l'image
* @return Le contenu de l'image
*/
public byte[] read(String name) {
try {
return filesService.readAsBytes(getPath(name));
} catch (IOException ex) {
throw new RuntimeException("Erreur lors de la lecture d'une image: " + ex.getMessage());
}
}
/**
* Écrit des données image sur le disque.
*
* @param image Le contenu du fichier
* @param name Le nom de l'image
* @return Si l'écriture du fichier s'est achevée
*/
public boolean write(MultipartFile image, String name) {
return filesService.write(image, getPath(name));
}
/**
* Supprime un fichier image.
*
* @param name Le nom de l'image
*/
public void delete(String name) {
filesService.delete(getPath(name));
}
/**
* Vérifie si un InputStream contient une image.
*
* @param input L'InputStream
* @return Si l'InputStream contient une image
*/
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 filesService.getPath(String.format("%s/%s", IMAGES_DIRECTORY, name));
}
}

View File

@ -1,35 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MarkdownFilesService {
private FilesService filesService;
@Autowired
public MarkdownFilesService(FilesService filesService) {
this.filesService = filesService;
}
/**
* Lit et fait le rendu en HTML d'un fichier MarkDown.
*
* @param path Le chemin vers la fichier (sans classpath:, depuis le dossier resources)
* @return Le MarkDown rendu en HTML
*/
public String render(String path) {
String fileContent = filesService.readResource(path);
Parser parser = Parser.builder().build();
Node document = parser.parse(fileContent);
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(document);
}
}

View File

@ -1,130 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutException;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Service
public class SimdutService {
private static final String SIMDUT_DIRECTORY = "simdut";
private FilesService filesService;
private MaterialJavaService materialService;
@Autowired
public SimdutService(FilesService filesService) {
this.filesService = filesService;
}
@Autowired
@Lazy
public void setMaterialService(MaterialJavaService materialService) {
this.materialService = materialService;
}
/**
* Vérifie si un produit a un fichier SIMDUT.
*
* @param material Le produit
* @return Si le produit a un fichier SIMDUT
*/
public boolean exists(Material material) {
return filesService.exists(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 exists(Long id) {
return exists(materialService.getById(id));
}
/**
* 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[] read(Material material) {
String path = getPath(material);
if (!filesService.exists(path)) return new byte[0];
try {
return filesService.readAsBytes(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[] read(Long id) {
return read(materialService.getById(id));
}
/**
* Écrit le fichier SIMDUT d'un produit.
*
* @param material Le produit
* @param simdut Le contenu du fichier SIMDUT à écrire
*/
public void write(Material material, MultipartFile simdut) {
if (!filesService.write(simdut, getPath(material))) throw new SimdutException(material);
}
/**
* Met à jour le fichier SIMDUT d'un produit
*
* @param simdut Le contenu du fichier SIMDUT mis à jour
* @param material Le produit du SIMDUT
*/
public void update(MultipartFile simdut, Material material) {
delete(material);
write(material, simdut);
}
/**
* Supprime le fichier SIMDUT pour un produit.
*
* @param material Le produit
*/
public void delete(Material material) {
filesService.delete(getPath(material));
}
/**
* Récupère le chemin vers le fichier SIMDUT d'un produit.
*
* @param material Le produit
* @return Le chemin vers le fichier SIMDUT du produit
*/
private String getPath(Material material) {
return filesService.getPath(String.format("%s/%s", SIMDUT_DIRECTORY, getSimdutFileName(material)));
}
/**
* Récupère le nom du fichier SIMDUT d'un produit.
*
* @param material Le produit
* @return Le nom du fichier SIMDUT du produit
*/
public String getSimdutFileName(Material material) {
return String.valueOf(material.getId());
}
}

View File

@ -1,9 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.RecipeService;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.XlsxExporter;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -16,11 +16,13 @@ import java.util.zip.ZipOutputStream;
@Service
public class XlsService {
private RecipeJavaService recipeService;
private RecipeService recipeService;
private Logger logger;
@Autowired
public XlsService(RecipeJavaService recipeService) {
public XlsService(RecipeService recipeService, Logger logger) {
this.recipeService = recipeService;
this.logger = logger;
}
/**
@ -30,7 +32,7 @@ public class XlsService {
* @return Le fichier XLS de la recette
*/
public byte[] generate(Recipe recipe) {
return new XlsxExporter().generate(recipe);
return new XlsxExporter(logger).generate(recipe);
}
/**
@ -49,7 +51,7 @@ public class XlsService {
* @return Le fichier ZIP contenant tous les fichiers XLS
*/
public byte[] generateForAll() throws IOException {
Preferences.logger.info("Exportation de toutes les couleurs en XLS");
logger.info("Exportation de toutes les couleurs en XLS");
byte[] zipContent;
Collection<Recipe> recipes = recipeService.getAll();

View File

@ -1,75 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityLinkedException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.Company;
import dev.fyloz.trial.colorrecipesexplorer.repository.CompanyRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.validation.constraints.NotNull;
@Service
public class CompanyJavaService extends AbstractJavaService<Company, CompanyRepository> {
private RecipeJavaService recipeService;
public CompanyJavaService() {
super(Company.class);
}
@Autowired
public void setCompanyDao(CompanyRepository companyRepository) {
this.repository = companyRepository;
}
// Pour éviter les dépendances circulaires
@Autowired
@Lazy
public void setRecipeService(RecipeJavaService recipeService) {
this.recipeService = recipeService;
}
/**
* Vérifie si une bannière correspondant à un nom existe.
*
* @param name Le nom de la bannière
* @return Si une bannière correspondant au nome existe
*/
public boolean existsByName(String name) {
return repository.existsByName(name);
}
/**
* Vérifie si une bannière est liée à une recette.
*
* @param company La bannière
* @return Si la bannière est liée à une recette
*/
public boolean isLinkedToRecipes(Company company) {
return recipeService.existsByCompany(company);
}
@Override
public Company save(@NotNull Company entity) {
if (existsByName(entity.getName()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.NAME, entity.getName());
return super.save(entity);
}
@Override
public void delete(Company entity) {
if (isLinkedToRecipes(entity)) throw new EntityLinkedException(type);
super.delete(entity);
}
@Deprecated(since = "1.3.0", forRemoval = true)
public void deleteIfNotLinked(Company company) {
if (!isLinkedToRecipes(company)) delete(company);
}
}

View File

@ -1,109 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialSaveDto;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialUpdateDto;
import dev.fyloz.trial.colorrecipesexplorer.repository.MaterialRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaNamedService;
import dev.fyloz.trial.colorrecipesexplorer.service.files.SimdutService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class MaterialJavaService extends AbstractJavaNamedService<Material, MaterialRepository> {
private MixMaterialJavaService mixQuantityService;
private SimdutService simdutService;
public MaterialJavaService() {
super(Material.class);
}
@Autowired
public void setMaterialDao(MaterialRepository materialRepository) {
this.repository = materialRepository;
}
@Autowired
public void setMixQuantityService(MixMaterialJavaService mixQuantityService) {
this.mixQuantityService = mixQuantityService;
}
@Autowired
public void setSimdutService(SimdutService simdutService) {
this.simdutService = simdutService;
}
/**
* Vérifie si des produits sont d'un type de produit
*
* @param materialType Le type de produit
* @return Si des produits sont du type de produit
*/
public boolean existsByMaterialType(MaterialType materialType) {
return repository.existsByMaterialType(materialType);
}
/**
* Vérifie si un produit est lié à un ou plusieurs mélanges.
*
* @param material Le produit à vérifier.
* @return Si le produit est lié à d'autres mélanges.
*/
public boolean isLinkedToMixes(Material material) {
return mixQuantityService.existsByMaterial(material);
}
/**
* Récupère tous les produits qui ne sont pas des types de mélange.
*
* @return Tous les produits qui ne sont pas des types de mélange
*/
@NotNull
public List<Material> getAllNotMixType() {
return getAll()
.stream()
.filter(m -> !m.isMixType())
.collect(Collectors.toList());
}
public Material save(MaterialSaveDto material) {
if (existsByName(material.getName()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.NAME, material.getName());
Material saved = save(material.toMaterial());
if (material.getSimdutFile() != null && !material.getSimdutFile().isEmpty())
simdutService.write(saved, material.getSimdutFile());
return saved;
}
@Override
public Material update(Material material) {
Optional<Material> materialByName = findOptional(repository.findByName(material.getName()));
if (materialByName.isPresent() && !Objects.equals(material.getId(), materialByName.get().getId()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.NAME, material.getName());
return super.update(material);
}
public Material update(MaterialUpdateDto material) {
simdutService.update(material.getSimdutFile(), material.toMaterial());
return update(material.toMaterial());
}
@Override
public void delete(Material material) {
simdutService.delete(material);
super.delete(material);
}
}

View File

@ -1,152 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteDefaultMaterialTypeException;
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotEditDefaultMaterialTypeException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MaterialTypeEditorDto;
import dev.fyloz.trial.colorrecipesexplorer.repository.MaterialTypeRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeKt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.validation.constraints.NotNull;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class MaterialTypeJavaService extends AbstractJavaService<MaterialType, MaterialTypeRepository> {
private MaterialJavaService materialService;
private List<MaterialType> defaultMaterialTypes = new LinkedList<>();
public MaterialTypeJavaService() {
super(MaterialType.class);
}
@Autowired
public void setMaterialTypeDao(MaterialTypeRepository materialTypeRepository) {
this.repository = materialTypeRepository;
}
@Autowired
public void setMaterialService(MaterialJavaService materialService) {
this.materialService = materialService;
}
public void setDefaultMaterialTypes(List<MaterialType> defaultMaterialTypes) {
this.defaultMaterialTypes = defaultMaterialTypes;
}
/**
* Ajoute un type de produit dans les types de produit par défaut.
*
* @param materialType Le type de produit
*/
public void addDefault(MaterialType materialType) {
defaultMaterialTypes.add(materialType);
}
/**
* Vérifie si un type de produit est un type de produit par défaut.
*
* @param materialType Le type de produit
* @return Si le type de produite est un type de produit par défaut
*/
public boolean isDefault(MaterialType materialType) {
return defaultMaterialTypes.contains(materialType);
}
/**
* Vérifie si un type de produit correspondant à un nom existe.
*
* @param name Le nom à vérifier
* @return Si un type de produit ayant le nom existe
*/
public boolean existsByName(String name) {
return repository.existsByName(name);
}
/**
* Vérifie si un type de produit correspondant à un préfixe existe.
*
* @param prefix Le préfixe à vérifier
* @return Si un type de produit ayant le préfixe existe
*/
public boolean existsByPrefix(String prefix) {
return repository.existsByPrefix(prefix);
}
/**
* Vérifie si un type de produit est utilisé par des produits.
*
* @param materialType Le type de produit
* @return si le type de produit est utilisé par des produits.
*/
public boolean isLinkedToMaterials(MaterialType materialType) {
return materialService.existsByMaterialType(materialType);
}
/**
* Récupère tous les type de produits qui ne sont pas des types de produit.
*
* @return Tous les type de produits qui ne sont pas des types de produit
*/
public List<MaterialType> getAllNotDefault() {
return getAll().stream()
.filter(t -> !isDefault(t))
.collect(Collectors.toList());
}
/**
* Récupère un type de produit par son nom.
*
* @param name Le nom du type de produit à récupérer
* @return Le type de produit correspondant au nom.
*/
public MaterialType getByName(String name) {
Optional<MaterialType> found = findOptional(repository.findByName(name));
if (found.isEmpty())
throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, name);
return found.get();
}
@Override
public MaterialType save(@NotNull MaterialType materialType) {
if (existsByName(materialType.getName()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.NAME, materialType.getName());
if (existsByPrefix(materialType.getPrefix()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MaterialTypeKt.IDENTIFIER_PREFIX_NAME, materialType.getPrefix());
return super.save(materialType);
}
public MaterialType update(MaterialTypeEditorDto materialTypeDto) {
MaterialType materialType = materialTypeDto.getMaterialType();
if (isDefault(materialTypeDto.getOldMaterialType()))
throw new CannotEditDefaultMaterialTypeException(materialTypeDto);
if (!existsByName(materialTypeDto.getOldName()))
throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, materialTypeDto.getOldName());
if (!materialTypeDto.getOldName().equals(materialType.getName()) && existsByName(materialType.getName()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.NAME, materialType.getName());
if (!materialTypeDto.getOldPrefix().equals(materialType.getPrefix()) && existsByPrefix(materialType.getPrefix()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MaterialTypeKt.IDENTIFIER_PREFIX_NAME, materialType.getPrefix());
return super.update(materialType);
}
@Override
public void delete(MaterialType materialType) {
if (isDefault(materialType)) throw new CannotDeleteDefaultMaterialTypeException(materialType);
super.delete(materialType);
}
}

View File

@ -1,141 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.*;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import dev.fyloz.trial.colorrecipesexplorer.utils.MixBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.Comparator;
import java.util.stream.Collectors;
@Service
public class MixJavaService extends AbstractJavaService<Mix, MixRepository> {
private MaterialJavaService materialService;
private MixMaterialJavaService mixQuantityService;
private MixTypeJavaService mixTypeService;
public MixJavaService() {
super(Mix.class);
}
@Autowired
public void setMixDao(MixRepository mixRepository) {
this.repository = mixRepository;
}
@Autowired
public void setMaterialService(MaterialJavaService materialService) {
this.materialService = materialService;
}
@Autowired
public void setMixQuantityService(MixMaterialJavaService mixQuantityService) {
this.mixQuantityService = mixQuantityService;
}
@Autowired
public void setMixTypeService(MixTypeJavaService mixTypeService) {
this.mixTypeService = mixTypeService;
}
/**
* Récupère les produits disponibles pour un mélange.
* Le mélange peut ne pas exister.
*
* @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(Recipe recipe, Long mixId) {
return existsById(mixId) ? getAvailableMaterialsForMix(getById(mixId)) : getAvailableMaterialsForNewMix(recipe);
}
/**
* Récupère les produits disponibles pour un mélange existant.
* `
*
* @param mix Le mélange
* @return Les produits disponibles pour ce mélange
*/
public Collection<Material> getAvailableMaterialsForMix(Mix mix) {
return getAvailableMaterialsForNewMix(mix.getRecipe())
.stream()
.filter(m -> !m.equals(mix.getMixType().getMaterial()))
.collect(Collectors.toList());
}
/**
* Récupère les produits disponibles pour un mélange inexistant.
*
* @param recipe La recette dans laquelle se trouve le mélange
* @return Les produits disponibles pour le nouveau mélange
*/
public Collection<Material> getAvailableMaterialsForNewMix(Recipe recipe) {
Collection<MixType> recipeMixTypes = recipe.getMixTypes();
return materialService
.getAll()
.stream()
.filter(m -> !m.isMixType() || recipeMixTypes.contains(mixTypeService.getByMaterial(m)))
.sorted(Comparator.comparing(Material::getName))
.sorted(Comparator.comparing(m -> m.getMaterialType().getName()))
.collect(Collectors.toList());
}
@Transactional
public void save(MixFormDto formDto) {
Mix mix = new MixBuilder(mixTypeService, materialService)
.withDto(formDto)
.build();
if (mix.getRecipe().containsMixType(mix.getMixType()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixKt.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
mixTypeService.save(mix.getMixType());
save(mix);
}
public void update(Mix mix, MixFormDto formDto) {
mix = new MixBuilder(mixTypeService, materialService)
.withMix(mix)
.withDto(formDto)
.build();
MixType mixType = mix.getMixType();
if (!formDto.getOldMixTypeName().equals(mixType.getName()) && mixTypeService.existsByName(formDto.getMixTypeName()) && mix.getRecipe().containsMixType(mixType))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixKt.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
if (materialService.existsByName(mixType.getName()) && !materialService.getByName(mixType.getName()).isMixType())
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, mixType.getName());
mixTypeService.update(mixType);
update(mix);
}
@Deprecated(since = "1.3.0", forRemoval = true)
public void deleteMix(Mix mix) {
mixQuantityService.deleteAll(mix.getMixMaterials());
delete(mix);
}
@Override
public void delete(Mix mix) {
mixQuantityService.deleteAll(mix.getMixMaterials());
super.delete(mix);
}
@Override
public void deleteById(Long id) {
delete(getById(id));
}
}

View File

@ -1,31 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial;
import dev.fyloz.trial.colorrecipesexplorer.repository.MixMaterialRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MixMaterialJavaService extends AbstractJavaService<MixMaterial, MixMaterialRepository> {
public MixMaterialJavaService() {
super(MixMaterial.class);
}
@Autowired
public void setMixQuantityDao(MixMaterialRepository mixMaterialRepository) {
this.repository = mixMaterialRepository;
}
/**
* Vérifie s'il y a un mélange qui contient un produit.
*
* @param material Le produit
* @return S'il y a un mélange qui contient le produit
*/
public boolean existsByMaterial(Material material) {
return repository.existsByMaterial(material);
}
}

View File

@ -1,99 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
import dev.fyloz.trial.colorrecipesexplorer.repository.MixTypeRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.validation.constraints.NotNull;
import java.util.Optional;
@Service
public class MixTypeJavaService extends AbstractJavaService<MixType, MixTypeRepository> {
private MaterialJavaService materialService;
public MixTypeJavaService() {
super(MixType.class);
}
@Autowired
public void setMixTypeDao(MixTypeRepository mixTypeRepository) {
this.repository = mixTypeRepository;
}
@Autowired
public void setMaterialService(MaterialJavaService materialService) {
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 repository.existsByName(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 = findOptional(repository.findByName(name));
if (found.isEmpty()) throw new EntityNotFoundException(type, ModelException.IdentifierType.NAME, name);
return found.get();
}
/**
* 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 = findOptional(repository.findByMaterial(material));
if (found.isEmpty())
throw new EntityNotFoundException(type, ModelException.IdentifierType.OTHER, material);
return found.get();
}
/**
* Crée un type de mélange.
*
* @param name Le nom du type de mélange
* @param materialType Le type de produit du type de mélange
* @return Le type de mélange créé
*/
public MixType create(String name, MaterialType materialType) {
Material mixTypeMaterial = new Material(name, 0f, true, materialType);
return new MixType(name, mixTypeMaterial);
}
@Override
public MixType save(@NotNull MixType entity) {
if (materialService.existsByName(entity.getName()))
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, entity.getName());
return super.save(entity);
}
@Override
public MixType update(MixType mixType) {
return super.update(mixType);
}
}

View File

@ -1,199 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.model.Company;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.RecipeEditorFormDto;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.RecipeExplorerFormDto;
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.files.ImagesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class RecipeJavaService extends AbstractJavaService<Recipe, RecipeRepository> {
private CompanyJavaService companyService;
private MixJavaService mixService;
private RecipeStepJavaService stepService;
private ImagesService imagesService;
public RecipeJavaService() {
super(Recipe.class);
}
@Autowired
public void setRecipeDao(RecipeRepository recipeRepository) {
this.repository = recipeRepository;
}
@Autowired
public void setCompanyService(CompanyJavaService companyService) {
this.companyService = companyService;
}
@Autowired
public void setMixService(MixJavaService mixService) {
this.mixService = mixService;
}
@Autowired
public void setStepService(RecipeStepJavaService stepService) {
this.stepService = stepService;
}
@Autowired
public void setImagesService(ImagesService imagesService) {
this.imagesService = imagesService;
}
/**
* Vérifie s'il y a une recette liée à une compagnie.
*
* @param company La compagnie
* @return S'il y a une recette liée à la compagnie
*/
public boolean existsByCompany(Company company) {
return repository.existsByCompany(company);
}
/**
* Récupère toutes les recettes pour une compagnie.
*
* @param company La compagnie
* @return Toutes les recettes pour la compagnie
*/
public Collection<Recipe> getAllByCompany(Company company) {
return repository.findAllByCompany(company);
}
/**
* Récupère toutes les recettes dans la base de données et les classes par compagnie.
*
* @return Un Map contenant les recettes classées par compagnie.
*/
public Map<Company, Collection<Recipe>> getAllMappedByCompany() {
return companyService.getAll().stream()
.collect(Collectors.toMap(c -> c, this::getAllByCompany));
}
/**
* Met à jour une recette ainsi que ses étapes.
*
* @param recipeDto Les informations de la recette à mettre à jour
* @return La recette mise à jour
*/
@Transactional
public Recipe updateRecipeAndSteps(RecipeEditorFormDto recipeDto) {
Recipe recipe = recipeDto.update(getById(recipeDto.getId()));
stepService.deleteAll(recipe.getSteps());
recipe.setSteps(stepService.createAllForRecipe(recipe, recipeDto.getStep()));
return update(recipe);
}
/**
* Met à jour les informations d'une recette trouvées dans l'explorateur de recette.
*
* @param form Le formulaire contenant les données mises à jour
*/
@Transactional
public void updateRecipeExplorerInfos(RecipeExplorerFormDto form) {
long recipeId = form.getRecipeId();
Map<Long, String> locations = form.getLocations();
String note = form.getNote();
Recipe recipe = getById(recipeId);
// Note
recipe.setNote(note);
update(recipe);
// Casiers
for (Map.Entry<Long, String> location : locations.entrySet()) {
Mix mix = mixService.getById(location.getKey());
mix.setLocation(location.getValue());
mixService.update(mix);
}
}
@Override
public void delete(Recipe recipe) {
super.delete(recipe);
removeAllFiles(recipe);
}
/**
* Récupère le nom des images liées à une recette.
*
* @param recipe La recette dont on veut récupérer les images
* @return Une liste contenant le nom des images liées à la recette.
*/
public List<String> getImageFiles(Recipe recipe) {
String imageName = getImageFileName(recipe);
File[] allImages = imagesService.getDirectoryFile().listFiles((d, n) -> n.startsWith(imageName));
if (allImages == null) return new ArrayList<>();
return Arrays.stream(allImages).map(File::getName).collect(Collectors.toList());
}
/**
* Récupère l'index de la prochaine image pour une recette.
*
* @param recipe La recette
* @return L'index de la prochaine image pour la recette
*/
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 + "-", "").replace(".jpeg", ""))).collect(Collectors.toList());
return indexes.size() > 0 ? Collections.max(indexes) + 1 : 0;
}
/**
* Récupère le nom des fichiers image d'une recette.
*
* @param recipe La recette
* @return Le nom des fichiers image de la recette
*/
public String getImageFileName(Recipe recipe) {
return recipe.getId().toString();
}
/**
* Récupère le nom du fichier image d'une recette avec le prochain index disponible.
*
* @param recipe La recette
* @return Le nom du fichier image de la recette avec le prochain index disponible
*/
public String getImageFileNameWithIndex(Recipe recipe) {
return getImageFileNameWithIndex(recipe, getNextImageIndex(recipe));
}
/**
* Récupère le nom du fichier image d'une recette avec un index.
*
* @param recipe La recette
* @param index L'index du fichier image
* @return Le nom du fichier image de la recette avec l'index
*/
public String getImageFileNameWithIndex(Recipe recipe, int index) {
return String.format("%s-%s", getImageFileName(recipe), index);
}
/**
* Supprime tous les fichiers image d'une recette.
*
* @param recipe La recette
*/
private void removeAllFiles(Recipe recipe) {
getImageFiles(recipe).forEach(f -> imagesService.delete(f));
}
}

View File

@ -1,46 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service.model;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeStep;
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeStepRepository;
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class RecipeStepJavaService extends AbstractJavaService<RecipeStep, RecipeStepRepository> {
public RecipeStepJavaService() {
super(RecipeStep.class);
}
@Autowired
public void setStepDao(RecipeStepRepository recipeStepRepository) {
this.repository = recipeStepRepository;
}
/**
* Crée une étape pour une recette.
*
* @param recipe La recette
* @param message Le message de l'étape à créer
*/
public RecipeStep createForRecipe(Recipe recipe, String message) {
return new RecipeStep(recipe, message);
}
/**
* Crée toutes les étapes pour une recette.
*
* @param recipe La recette
* @param messages Tous les messages des étapes à créer
*/
@Transactional
public List<RecipeStep> createAllForRecipe(Recipe recipe, List<String> messages) {
return messages.stream().map(m -> createForRecipe(recipe, m)).collect(Collectors.toList());
}
}

View File

@ -1,64 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.utils;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.net.URISyntaxException;
public class ControllerUtils {
private static final String HTTP_SCHEME = "http";
private static final String HTTPS_SCHEME = "https";
public static String redirect(String viewName) {
return String.format("redirect:/%s", viewName);
}
public static URI getUri(HttpServletRequest request) throws URISyntaxException {
return new URI(request.getRequestURL().toString());
}
public static String getUrlFromURI(URI uri) {
String host = uri.getHost();
int port = uri.getPort();
String scheme = getScheme();
return String.format("%s://%s:%s", scheme, host, port);
}
public static String getCurrentBaseUrl() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) return "";
HttpServletRequest request = attributes.getRequest();
String port = ":" + (Preferences.urlUsePort ? request.getServerPort() : "");
return String.format("%s://%s%s%s", getScheme(), request.getServerName(), port, request.getContextPath());
}
public static String getLatestUrl() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) return "";
HttpServletRequest request = attributes.getRequest();
try {
String currentDomainName = getUrlFromURI(getUri(request));
String referer = request.getHeader("referer");
if (referer == null) return currentDomainName;
String refererURL = getUrlFromURI(new URI(referer));
return refererURL.equals(currentDomainName) ? referer : currentDomainName;
} catch (URISyntaxException e) {
return "";
}
}
private static String getScheme() {
return Preferences.urlUseHttps ? HTTPS_SCHEME : HTTP_SCHEME;
}
}

View File

@ -1,116 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.utils;
import dev.fyloz.trial.colorrecipesexplorer.model.*;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixTypeJavaService;
import java.util.*;
public class MixBuilder {
private MixTypeJavaService mixTypeService;
private MaterialJavaService materialService;
private Long id;
private Recipe recipe;
private MixType mixType;
private String location;
private Collection<MixMaterial> mixMaterials = new ArrayList<>();
private Map<String, Float> quantities = new LinkedHashMap<>();
public MixBuilder(MixTypeJavaService mixTypeService, MaterialJavaService materialService) {
this.mixTypeService = mixTypeService;
this.materialService = materialService;
}
public MixBuilder withMix(Mix mix) {
this.id = mix.getId();
this.recipe = mix.getRecipe();
this.mixType = mix.getMixType();
this.location = mix.getLocation();
this.mixMaterials = mix.getMixMaterials();
return this;
}
public MixBuilder withDto(MixFormDto dto) {
String mixTypeName = dto.getMixTypeName();
if (this.mixType == null) {
this.mixType = mixTypeService.create(mixTypeName, dto.getMaterialType());
} else {
this.mixType = new MixType(this.mixType.getId(), this.mixType.getName(), this.mixType.getMaterial());
if (materialService.existsByName(mixTypeName)) {
this.mixType.setName(mixTypeName);
this.mixType.setMaterial(materialService.getByName(mixTypeName));
} else {
this.mixType.setName(mixTypeName);
this.mixType.getMaterial().setName(mixTypeName);
}
this.mixType.getMaterial().setMaterialType(dto.getMaterialType());
}
this.recipe = dto.getRecipe();
for (int i = 0; i < dto.getMaterials().size(); i++)
quantities.put(dto.getMaterials().get(i), dto.getQuantities().get(i));
return this;
}
public MixBuilder withId(Long id) {
this.id = id;
return this;
}
public MixBuilder withRecipe(Recipe recipe) {
this.recipe = recipe;
return this;
}
public MixBuilder withMixType(MixType mixType) {
this.mixType = mixType;
return this;
}
public MixBuilder withMixQuantity(MixMaterial mixMaterial) {
this.mixMaterials.add(mixMaterial);
return this;
}
public MixBuilder withMixQuantities(List<MixMaterial> mixQuantities) {
this.mixMaterials = mixQuantities;
return this;
}
public Mix build() {
Mix mix = new Mix(this.id, this.location, this.recipe, this.mixType, new ArrayList<>());
createMixQuantities(mix);
mix.getMixMaterials().addAll(this.mixMaterials);
return mix;
}
private void createMixQuantities(Mix mix) {
List<MixMaterial> mixQuantities = new ArrayList<>();
for (Map.Entry<String, Float> quantityEntry : quantities.entrySet()) {
Material material = materialService.getByName(quantityEntry.getKey());
Float quantity = quantityEntry.getValue();
mixQuantities.add(new MixMaterial(mix, material, quantity));
}
this.mixMaterials = mixQuantities;
}
}

View File

@ -1,8 +1,5 @@
package dev.fyloz.trial.colorrecipesexplorer.utils;
import dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
@ -17,6 +14,8 @@ import java.util.Collection;
public class PdfBuilder {
private static final String PATH_FONT_ARIAL_BOLD = "classpath:fonts/arialbd.ttf";
private PDFont font;
private PDDocument document = new PDDocument();
private PDPage page = new PDPage();
@ -33,7 +32,7 @@ public class PdfBuilder {
this.lineSpacing = (int) (this.fontSize * 1.5f);
document.addPage(page);
font = PDType0Font.load(document, resourceLoader.getResource(WebsitePaths.FONT_ARIAL_BOLD).getInputStream());
font = PDType0Font.load(document, resourceLoader.getResource(PATH_FONT_ARIAL_BOLD).getInputStream());
}
public PdfBuilder addLine(String text, boolean bold, int marginTop) {
@ -88,14 +87,44 @@ public class PdfBuilder {
contentStream.newLineAtOffset(-textX, -textY); // Réinitialise la position pour la prochaine ligne
}
@Data
@AllArgsConstructor
public static class PdfLine {
private String text;
private boolean bold;
private int marginTop;
public PdfLine() {
}
public PdfLine(String text, boolean bold, int marginTop) {
this.text = text;
this.bold = bold;
this.marginTop = marginTop;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isBold() {
return bold;
}
public void setBold(boolean bold) {
this.bold = bold;
}
public int getMarginTop() {
return marginTop;
}
public void setMarginTop(int marginTop) {
this.marginTop = marginTop;
}
}
}

View File

@ -1,30 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web;
public class StringBank {
// Types de réponse
public static final String RESPONSE_ERROR = "error";
public static final String RESPONSE_SUCCESS = "success";
public static final String RESPONSE_REASON = "reason";
// Types d'attributs communs
public static final String MATERIALS = "materials";
public static final String MATERIAL = "material";
public static final String MATERIAL_ID = "materialID";
public static final String MATERIAL_CODE = "materialCode";
public static final String MATERIAL_TYPES = "materialTypes";
public static final String MATERIAL_TYPE = "materialType";
public static final String RECIPES = "recipes";
public static final String RECIPE = "recipe";
public static final String RECIPE_ID = "recipeId";
public static final String RECIPE_CODE = "recipeCode";
public static final String MIXES = "mixes";
public static final String MIX = "mix";
public static final String MIX_ID = "mixID";
public static final String MIX_TYPE = "mixType";
public static final String MIX_TYPES = "mixTypes";
public static final String COMPANIES = "companies";
public static final String COMPANY = "company";
public static final String COMPANY_ID = "companyID";
}

View File

@ -1,73 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web;
public class WebsitePaths {
// Autres
public static final String INDEX = "index";
public static final String SIMDUT_FILES = "simdut/{id}";
public static final String PASSWORD_VALIDATION = "password/valid";
public static final String RECIPE_XLS = "recipe/xls/{id}";
public static final String ALL_RECIPES_XLS = "recipe/xls";
public static final String ERROR = "error";
public static final String CLOSE_TAB = "closeTab";
public static final String UPDATES = "updates";
public static final String UPDATES_GET = "updates/get";
public static final String FONT_ARIAL_BOLD = "classpath:fonts/arialbd.ttf";
// Images
public static final String IMAGES_FILES = "images/{image}";
public static final String ADD_IMAGE = "images/add";
public static final String ADD_IMAGE_SPECIFIC = "images/add/{id}";
public static final String DELETE_IMAGE = "images/delete/{image}";
// Touch up kits
public static final String TOUCHUP = "touchup";
public static final String TOUCHUP_PDF = "touchup/pdf";
public static final String TOUCHUP_PTOUCH = "touchup/ptouch";
public static final String TOUCHUP_PTOUCH_PAGE = "touchupPtouch";
// Inventaire
public static final String INVENTORY = "inventory";
public static final String USE_INVENTORY = "inventory/use";
// Recettes
public static final String EXPLORER_RECIPE = "recipe/explore";
public static final String EXPLORER_RECIPE_SPECIFIC = "recipe/explore/{id}";
public static final String CREATOR_RECIPE = "recipe/creator";
public static final String EDITOR_RECIPE = "recipe/editor";
public static final String EDITOR_RECIPE_SPECIFIC = "recipe/editor/{id}";
public static final String EDITOR_RECIPE_EDITOR = "recipe/edit";
public static final String REMOVER_RECIPE = "recipe/remover";
public static final String REMOVER_RECIPE_SPECIFIC = "recipe/remover/{id}";
// Compagnies
public static final String CREATOR_COMPANY = "company/creator";
public static final String REMOVER_COMPANY = "company/remover";
public static final String REMOVER_COMPANY_SPECIFIC = "company/remover/{id}";
// Matériaux
public static final String CREATOR_MATERIAL = "material/creator";
public static final String EDIT_MATERIAL_SIMDUT = "material/simdut";
public static final String EDIT_MATERIAL_SIMDUT_SPECIFIC = "material/simdut/{id}";
public static final String REMOVER_MATERIAL = "material/remover";
public static final String REMOVER_MATERIAL_SPECIFIC = "material/remover/{id}";
public static final String EDITOR_MATERIAL = "material/editor";
public static final String EDITOR_MATERIAL_SPECIFIC = "material/editor/{id}";
public static final String EDITOR_MATERIAL_EDITOR = "material/edit";
// Types de matériaux
public static final String CREATOR_MATERIAL_TYPE = "materialType/creator";
public static final String REMOVER_MATERIAL_TYPE = "materialType/remover";
public static final String REMOVER_MATERIAL_TYPE_SPECIFIC = "materialType/remover/{id}";
public static final String EDITOR_MATERIAL_TYPE = "materialType/editor";
public static final String EDITOR_MATERIAL_TYPE_SPECIFIC = "materialType/editor/{id}";
public static final String EDITOR_MATERIAL_TYPE_EDITOR = "materialType/edit";
// Mélanges
public static final String CREATOR_MIX = "mix/creator";
public static final String CREATOR_MIX_SPECIFIC = "mix/creator/{id}";
public static final String EDITOR_MIX = "mix/editor";
public static final String EDITOR_MIX_SPECIFIC = "mix/editor/{id}";
public static final String REMOVER_MIX_SPECIFIC = "mix/remover/{id}";
public static final String MATERIAL_SELECTOR_MIX = "mix/selector/{recipeId}/{mixId}";
public static final String MATERIAL_SELECTOR_FRAGMENT = "mix/selector.html :: materialSelector";
}

View File

@ -1,14 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.angular
import org.springframework.context.annotation.Profile
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
@Controller
@Profile("angular")
class AngularController {
@GetMapping("/explore")
fun frontend(): String {
return "forward:/"
}
}

View File

@ -1,53 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.ERROR;
@Controller
@Profile("thymeleaf")
public class CREErrorController implements ErrorController {
@RequestMapping("/error")
public ModelAndView handleError(HttpServletRequest request) {
ModelResponseBuilder responseBuilder = new ModelResponseBuilder("error");
responseBuilder.addAttribute("referer", request.getHeader("referer"));
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
ResponseCode responseCode = ResponseCode._500;
if (status != null) {
int statusCode = Integer.parseInt(status.toString());
switch (statusCode) {
case 401:
responseCode = ResponseCode._401;
break;
case 404:
responseCode = ResponseCode._404;
break;
default:
responseCode = ResponseCode._500;
break;
}
}
responseBuilder.addResponseCode(responseCode);
return responseBuilder.build();
}
@Override
public String getErrorPath() {
return ERROR;
}
}

View File

@ -1,20 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode
import dev.fyloz.trial.colorrecipesexplorer.utils.ControllerUtils
import org.springframework.web.servlet.ModelAndView
fun modelAndView(model: ModelAndView = ModelAndView(), op: ModelAndView.() -> Unit = {}) = model.apply {
addObject("baseUrl", ControllerUtils.getCurrentBaseUrl())
addObject("referer", ControllerUtils.getLatestUrl())
apply(op)
}
fun modelAndView(viewName: String, op: ModelAndView.() -> Unit = {}) = modelAndView(ModelAndView(viewName), op)
fun ModelAndView.message(responseCode: ResponseCode, vararg parameters: Any?) {
addObject(if (responseCode.type == ResponseCode.ResponseCodeType.ERROR) "error" else "success", "response.${responseCode.code}")
parameters.forEachIndexed { index, param ->
addObject("responseArg${index + 1}", param)
}
}

View File

@ -1,53 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.service.PasswordService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.INDEX;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.PASSWORD_VALIDATION;
@Controller
@Profile("thymeleaf")
public class IndexController {
private RecipeJavaService recipeService;
@Autowired
public IndexController(RecipeJavaService recipeService) {
this.recipeService = recipeService;
}
/**
* Affiche la page d'acceuil.
*
* @return La page à afficher.
*/
@GetMapping({INDEX, "/"})
public ModelAndView getPage() {
return new ModelResponseBuilder(INDEX)
.addResponseData(ResponseDataType.RECIPE_MAP, recipeService.getAllMappedByCompany())
.build();
}
/**
* Valide un mot de passe reçu dans une requête HTTP POST, dans le champ "password".
*
* @param data Corps de la requête HTTP
* @return Si le mot de passe est valide.
*/
@PostMapping(value = PASSWORD_VALIDATION, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public boolean validatePassword(@RequestBody Map<String, Object> data) {
return PasswordService.isValid((String) data.get("password"));
}
}

View File

@ -1,71 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf;
import dev.fyloz.trial.colorrecipesexplorer.exception.TooLowQuantityException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.JSONResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.InventoryDto;
import dev.fyloz.trial.colorrecipesexplorer.service.InventoryService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
import java.util.Map;
import static dev.fyloz.trial.colorrecipesexplorer.web.StringBank.RESPONSE_REASON;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.INVENTORY;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.USE_INVENTORY;
@Controller
@Profile("thymeleaf")
public class InventoryController {
private InventoryService inventoryService;
private MaterialJavaService materialService;
private MaterialTypeJavaService materialTypeService;
@Autowired
public InventoryController(InventoryService inventoryService, MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
this.inventoryService = inventoryService;
this.materialService = materialService;
this.materialTypeService = materialTypeService;
}
@GetMapping(INVENTORY)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(INVENTORY)
.addResponseData(ResponseDataType.MATERIALS, materialService.getAllNotMixType())
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
.build();
}
@PostMapping(value = USE_INVENTORY, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Transactional
public Map<String, Object> consumeMaterials(@RequestBody List<InventoryDto> mixes) {
JSONResponseBuilder jsonResponseBuilder = new JSONResponseBuilder();
try {
inventoryService.use(mixes);
jsonResponseBuilder.addResponseCode(ResponseCode.SUCCESS_USING_MATERIALS);
} catch (TooLowQuantityException ex) {
jsonResponseBuilder.addResponseCode(ResponseCode.NOT_ENOUGH_MATERIAL, ex.getMaterial().getName())
.addAttribute(RESPONSE_REASON, ex.getResponse());
}
return jsonResponseBuilder.build();
}
}

View File

@ -1,66 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.service.files.MarkdownFilesService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.StringBank.MATERIALS;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class OthersController {
private MixJavaService mixService;
private RecipeJavaService recipeService;
private MarkdownFilesService markdownService;
@Autowired
public OthersController(MixJavaService mixService, RecipeJavaService recipeService, MarkdownFilesService markdownService) {
this.mixService = mixService;
this.recipeService = recipeService;
this.markdownService = markdownService;
}
@GetMapping(CLOSE_TAB)
public ModelAndView getCloseTab() {
return new ModelResponseBuilder(CLOSE_TAB).build();
}
@GetMapping(MATERIAL_SELECTOR_MIX)
public ModelAndView getMaterialSelectorFragment(@PathVariable Long recipeId, @PathVariable Long mixId) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(MATERIAL_SELECTOR_FRAGMENT);
try {
modelResponseBuilder.addAttribute(MATERIALS, mixService.getAvailableMaterialsForMixId(recipeService.getById(recipeId), mixId));
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, recipeId);
}
return modelResponseBuilder.build();
}
@GetMapping(value = UPDATES)
public ModelAndView getUpdatesPage() {
return new ModelResponseBuilder(UPDATES).build();
}
@GetMapping(value = UPDATES_GET, produces = MediaType.TEXT_HTML_VALUE)
@ResponseBody
public ResponseEntity<String> getUpdates() {
return new ResponseEntity<>(markdownService.render("updates.md"), HttpStatus.OK);
}
}

View File

@ -1,73 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.web.response.JSONResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.RecipeExplorerFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class RecipeExplorerController {
private RecipeJavaService recipeService;
@Autowired
public RecipeExplorerController(RecipeJavaService recipeService) {
this.recipeService = recipeService;
}
@GetMapping(EXPLORER_RECIPE_SPECIFIC)
public ModelAndView getPage(@PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(EXPLORER_RECIPE);
try {
Recipe recipe = recipeService.getById(id);
return modelResponseBuilder
.addResponseData(ResponseDataType.RECIPE, recipe)
.addResponseData(ResponseDataType.MIXES, recipe.getMixesSortedById())
.addResponseData(ResponseDataType.IMAGES, recipeService.getImageFiles(recipe))
.build();
} catch (EntityNotFoundException e) {
return modelResponseBuilder
.withView(INDEX)
.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id)
.build();
}
}
@PostMapping(value = EXPLORER_RECIPE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Map<String, Object> saveRecipeInformations(@RequestBody RecipeExplorerFormDto form) {
JSONResponseBuilder responseBuilder = new JSONResponseBuilder();
try {
recipeService.updateRecipeExplorerInfos(form);
responseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_RECIPE_INFORMATIONS);
} catch (EntityNotFoundException e) {
responseBuilder.addResponseCode(
e.getType().equals(Recipe.class) ?
ResponseCode.RECIPE_NOT_FOUND :
ResponseCode.MIX_NOT_FOUND,
e.getRequestedId()
);
}
return responseBuilder.build();
}
}

View File

@ -1,55 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.model.Company;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.service.model.CompanyJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CREATOR_COMPANY;
@Controller
@Profile("thymeleaf")
public class CompanyCreatorController {
private CompanyJavaService companyService;
@Autowired
public CompanyCreatorController(CompanyJavaService companyService) {
this.companyService = companyService;
}
@GetMapping(CREATOR_COMPANY)
public ModelAndView getPage(ModelAndView model, Company company) {
return new ModelResponseBuilder(model)
.withView(CREATOR_COMPANY)
.addResponseData(ResponseDataType.COMPANY, company)
.build();
}
@PostMapping(value = CREATOR_COMPANY, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ModelAndView createCompany(@ModelAttribute @Valid Company company) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
company = companyService.save(company);
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_COMPANY, company.getName());
} catch (EntityAlreadyExistsException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_ALREADY_EXIST, company.getName());
}
return getPage(modelResponseBuilder.build(), company);
}
}

View File

@ -1,66 +0,0 @@
//package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
//
//import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutException;
//import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
//import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
//import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
//import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
//import dev.fyloz.trial.colorrecipesexplorer.model.Material;
//import dev.fyloz.trial.colorrecipesexplorer.services.model.MaterialService;
//import dev.fyloz.trial.colorrecipesexplorer.services.model.MaterialTypeService;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.http.MediaType;
//import org.springframework.lang.Nullable;
//import org.springframework.stereotype.Controller;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.PostMapping;
//import org.springframework.web.multipart.MultipartFile;
//import org.springframework.web.servlet.ModelAndView;
//
//import javax.validation.Valid;
//
//import java.util.Optional;
//
//import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CREATOR_MATERIAL;
//
//@Controller
//public class MaterialCreatorController {
//
// private MaterialService materialService;
// private MaterialTypeService materialTypeService;
//
// @Autowired
// public MaterialCreatorController(MaterialService materialService, MaterialTypeService materialTypeService) {
// this.materialService = materialService;
// this.materialTypeService = materialTypeService;
// }
//
// @GetMapping(CREATOR_MATERIAL)
// public ModelAndView getPage(ModelAndView model, Material material) {
// return new ModelResponseBuilder(model)
// .withView(CREATOR_MATERIAL)
//// .addResponseData(ResponseDataType.MATERIAL, material)
//// .addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
// .build();
// }
//
// @PostMapping(value = CREATOR_MATERIAL, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
// public ModelAndView createMaterial(@Valid Material material, MultipartFile simdut) {
// ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
//
// try {
// materialService.save(material, simdut);
// return getPage(
// modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL, material.getName()).build(),
// new Material()
// );
// } catch (EntityAlreadyExistsException ex) {
// modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_ALREADY_EXIST, material.getName());
// } catch (SimdutException ex) {
// modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL, material.getName());
// modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_SIMDUT);
// }
//
// return getPage(modelResponseBuilder.build(), material);
// }
//}

View File

@ -1,49 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators
import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialSaveDto
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService
import dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CREATOR_MATERIAL
import dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.message
import dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.modelAndView
import org.springframework.context.annotation.Profile
import org.springframework.http.MediaType
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.servlet.ModelAndView
import javax.validation.Valid
@Controller
@Profile("thymeleaf")
class MaterialCreatorController(val materialService: MaterialJavaService, val materialTypeService: MaterialTypeJavaService) {
@GetMapping(CREATOR_MATERIAL)
fun getPage(model: ModelAndView, @RequestParam(required = false) material: Material? = null): ModelAndView {
return modelAndView(model) {
viewName = CREATOR_MATERIAL
addObject("material", material ?: Material())
addObject("materialTypes", materialTypeService.all)
}
}
@PostMapping(value = [CREATOR_MATERIAL], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
fun createMaterial(@Valid material: Material, simdut: MultipartFile): ModelAndView {
return getPage(modelAndView {
try {
materialService.save(MaterialSaveDto(material.name, material.inventoryQuantity, material.materialType!!, simdut))
message(ResponseCode.SUCCESS_SAVING_MATERIAL, material.name)
} catch (ex: EntityAlreadyExistsException) {
message(ResponseCode.MATERIAL_ALREADY_EXIST, material.name)
} catch (ex: SimdutException) {
message(ResponseCode.SUCCESS_SAVING_MATERIAL, material.name)
message(ResponseCode.ERROR_SAVING_SIMDUT)
}
})
}
}

View File

@ -1,62 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.utils.ControllerUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CREATOR_MATERIAL_TYPE;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.INDEX;
@Controller
@Profile("thymeleaf")
public class MaterialTypeCreatorController {
private MaterialTypeJavaService materialTypeService;
@Autowired
public MaterialTypeCreatorController(MaterialTypeJavaService materialTypeService) {
this.materialTypeService = materialTypeService;
}
@GetMapping(CREATOR_MATERIAL_TYPE)
public ModelAndView getPage(ModelAndView model, MaterialType materialType) {
return new ModelResponseBuilder(model)
.withView(CREATOR_MATERIAL_TYPE)
.addResponseData(ResponseDataType.MATERIAL_TYPE, materialType == null ? new MaterialType() : materialType)
.build();
}
@PostMapping(CREATOR_MATERIAL_TYPE)
public ModelAndView createMaterialType(@Valid MaterialType materialType) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(ControllerUtils.redirect(INDEX));
try {
materialTypeService.save(materialType);
return getPage(
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL_TYPE, materialType.getName()).build(),
null
);
} catch (EntityAlreadyExistsException ex) {
if (ex.getIdentifierType() == ModelException.IdentifierType.NAME) {
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_ALREADY_EXIST, materialType.getName());
} else {
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_ALREADY_EXIST_PREFIX, materialType.getPrefix());
}
}
return getPage(modelResponseBuilder.build(), materialType);
}
}

View File

@ -1,89 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.MixKt;
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.ServiceKt;
import dev.fyloz.trial.colorrecipesexplorer.service.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class MixCreatorController {
private MixJavaService mixService;
private RecipeJavaService recipeService;
private MaterialJavaService materialService;
private MaterialTypeJavaService materialTypeService;
@Autowired
public MixCreatorController(MixJavaService mixService, RecipeJavaService recipeService, MaterialJavaService materialService, MixTypeJavaService mixTypeService, MaterialTypeJavaService materialTypeService) {
this.mixService = mixService;
this.recipeService = recipeService;
this.materialService = materialService;
this.materialTypeService = materialTypeService;
}
@GetMapping(CREATOR_MIX_SPECIFIC)
public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model)
.withView(CREATOR_MIX);
try {
Recipe recipe = recipeService.getById(id);
modelResponseBuilder
.addResponseData(ResponseDataType.RECIPE, recipe)
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
.addResponseData(ResponseDataType.MATERIALS_JSON, ServiceKt.asJson(mixService.getAvailableMaterialsForNewMix(recipe)));
if (materialService.getAll().isEmpty())
modelResponseBuilder.addResponseData(ResponseDataType.BLOCK_BUTTON, true);
} catch (EntityNotFoundException ex) {
modelResponseBuilder
.withRedirect(EDITOR_RECIPE);
}
return modelResponseBuilder.build();
}
@PostMapping(value = CREATOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ModelAndView createMix(@ModelAttribute @Valid MixFormDto formDto) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
mixService.save(formDto);
return modelResponseBuilder
.withRedirect(EDITOR_RECIPE_SPECIFIC, formDto.getRecipe().getId())
.build();
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, ex.getRequestedId());
} catch (EntityAlreadyExistsException ex) {
if (ex.getIdentifierName().equals(MixKt.IDENTIFIER_MIX_TYPE_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
else if (ex.getIdentifierName().equals(MixTypeKt.IDENTIFIER_MATERIAL_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
}
return getPage(modelResponseBuilder.build(), formDto.getRecipe().getId());
}
}

View File

@ -1,57 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.service.model.CompanyJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CREATOR_RECIPE;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.EDITOR_RECIPE_SPECIFIC;
@Controller
@Profile("thymeleaf")
public class RecipeCreatorController {
private RecipeJavaService recipeService;
private CompanyJavaService companyService;
@Autowired
public RecipeCreatorController(RecipeJavaService recipeService, CompanyJavaService companyService) {
this.recipeService = recipeService;
this.companyService = companyService;
}
@GetMapping(CREATOR_RECIPE)
public ModelAndView getPage(ModelAndView model, Recipe recipe) {
ModelResponseBuilder responseBuilder = new ModelResponseBuilder(model)
.withView(CREATOR_RECIPE)
.addResponseData(ResponseDataType.COMPANIES, companyService.getAll())
.addResponseData(ResponseDataType.RECIPE, recipe == null ? new Recipe() : recipe);
if (companyService.getAll().isEmpty()) {
responseBuilder.addResponseCode(ResponseCode.NO_COMPANY)
.addResponseData(ResponseDataType.BLOCK_BUTTON, true);
}
return responseBuilder.build();
}
@PostMapping(CREATOR_RECIPE)
public ModelAndView createRecipe(@Valid Recipe recipe) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
long id = recipeService.save(recipe).getId();
return modelResponseBuilder.withRedirect(EDITOR_RECIPE_SPECIFIC, id).build();
}
}

View File

@ -1,108 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;
import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialUpdateDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class MaterialEditorController {
private MaterialJavaService materialService;
private MaterialTypeJavaService materialTypeService;
@Autowired
public MaterialEditorController(MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
this.materialService = materialService;
this.materialTypeService = materialTypeService;
}
@GetMapping(EDITOR_MATERIAL)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(EDITOR_MATERIAL)
.addResponseData(ResponseDataType.MATERIALS, materialService.getAllNotMixType())
.build();
}
@GetMapping(EDITOR_MATERIAL_SPECIFIC)
public ModelAndView getEditPage(ModelAndView model, @PathVariable Long id, Material material) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MATERIAL_EDITOR);
try {
if (material.getName() == null) material = materialService.getById(id);
return modelResponseBuilder
.addResponseData(ResponseDataType.MATERIAL, material)
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
.build();
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, id);
}
return getPage(modelResponseBuilder.build());
}
@PostMapping(value = EDITOR_MATERIAL, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ModelAndView updateMaterial(Material material) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
material = materialService.update(material);
return getPage(modelResponseBuilder
.addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL, material.getName())
.build());
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, material.getId());
} catch (EntityAlreadyExistsException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_ALREADY_EXIST, material.getName());
}
return getEditPage(modelResponseBuilder.build(), material.getId(), material);
}
@GetMapping(value = EDIT_MATERIAL_SIMDUT_SPECIFIC)
public ModelAndView getSimdutPage(ModelAndView model, @PathVariable Long id) {
return new ModelResponseBuilder(model)
.withView(EDIT_MATERIAL_SIMDUT)
.addResponseData(ResponseDataType.MATERIAL_ID, id)
.build();
}
@PostMapping(value = EDIT_MATERIAL_SIMDUT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ModelAndView updateSimdut(Long id, MultipartFile simdut) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_MATERIAL_SPECIFIC, id);
try {
Material material = materialService.getById(id);
materialService.update(new MaterialUpdateDto(material.getId(), material.getName(), material.getInventoryQuantity(), material.getMaterialType(), simdut));
} catch (EntityNotFoundException ex) {
return getSimdutPage(
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, id).build(),
id
);
} catch (SimdutException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_SIMDUT);
}
return modelResponseBuilder.build();
}
}

View File

@ -1,79 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotEditDefaultMaterialTypeException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MaterialTypeEditorDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeKt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class MaterialTypeEditorController {
private MaterialTypeJavaService materialTypeService;
@Autowired
public MaterialTypeEditorController(MaterialTypeJavaService materialTypeService) {
this.materialTypeService = materialTypeService;
}
@GetMapping(EDITOR_MATERIAL_TYPE)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(EDITOR_MATERIAL_TYPE)
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAllNotDefault())
.build();
}
@GetMapping(EDITOR_MATERIAL_TYPE_SPECIFIC)
public ModelAndView getEditPage(ModelAndView model, @PathVariable Long id, MaterialTypeEditorDto materialTypeDto) {
ModelResponseBuilder responseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MATERIAL_TYPE_EDITOR);
try {
if (materialTypeDto.getName() == null) materialTypeDto = new MaterialTypeEditorDto(materialTypeService.getById(id));
return responseBuilder
.addResponseData(ResponseDataType.MATERIAL_TYPE_DTO, materialTypeDto)
.build();
} catch (EntityNotFoundException ex) {
return getPage(responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_NOT_FOUND, id).build());
}
}
@PostMapping(value = EDITOR_MATERIAL_TYPE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ModelAndView updateMaterialType(MaterialTypeEditorDto materialTypeDto) {
ModelResponseBuilder responseBuilder = new ModelResponseBuilder();
try {
materialTypeService.update(materialTypeDto);
return getPage(responseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL_TYPE, materialTypeDto.getMaterialType().getName()).build());
} catch (EntityNotFoundException ex) {
return getPage(responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_NOT_FOUND, materialTypeDto.getOldName()).build());
} catch (EntityAlreadyExistsException ex) {
if (ModelException.IdentifierType.NAME.equals(ex.getIdentifierType()))
responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_ALREADY_EXIST, materialTypeDto.getMaterialType().getName());
else if (MaterialTypeKt.IDENTIFIER_PREFIX_NAME.equals(ex.getIdentifierName()))
responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_ALREADY_EXIST_PREFIX, materialTypeDto.getMaterialType().getPrefix());
} catch(CannotEditDefaultMaterialTypeException ex) {
responseBuilder.addResponseCode(ResponseCode.CANNOT_EDIT_DEFAULT_MATERIAL_TYPE);
}
return getEditPage(responseBuilder.build(), materialTypeDto.getMaterialType().getId(), materialTypeDto);
}
}

View File

@ -1,85 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixKt;
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class MixEditorController {
private MixJavaService mixService;
private MaterialJavaService materialService;
private MaterialTypeJavaService materialTypeService;
@Autowired
public MixEditorController(MixJavaService mixService, MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
this.mixService = mixService;
this.materialService = materialService;
this.materialTypeService = materialTypeService;
}
@GetMapping(EDITOR_MIX_SPECIFIC)
public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MIX);
try {
Mix mix = mixService.getById(id);
return modelResponseBuilder
.addResponseData(ResponseDataType.MIX, mix)
.addResponseData(ResponseDataType.MATERIAL_TYPE, mix.getMixType().getMaterial().getMaterialType())
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
.addResponseData(ResponseDataType.MIX_JSON, mixService.asJson(mix))
.addResponseData(ResponseDataType.MATERIALS_JSON, materialService.asJson(mixService.getAvailableMaterialsForMix(mix)))
.build();
} catch (EntityNotFoundException ex) {
return modelResponseBuilder
.withRedirect(EDITOR_RECIPE)
.build();
}
}
@PostMapping(value = EDITOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ModelAndView updateMix(@ModelAttribute @Valid MixFormDto formDto, @RequestParam("mixId") Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_RECIPE_SPECIFIC, formDto.getRecipe().getId());
try {
Mix mix = mixService.getById(id);
mixService.update(mix, formDto);
return modelResponseBuilder.build();
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id).build();
} catch (EntityAlreadyExistsException ex) {
if (ex.getIdentifierName().equals(MixTypeKt.IDENTIFIER_MATERIAL_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
else if (ex.getIdentifierName().equals(MixKt.IDENTIFIER_MIX_TYPE_NAME))
modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
else throw new EntityAlreadyExistsException(ex);
}
return getPage(modelResponseBuilder.build(), id);
}
}

View File

@ -1,79 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.RecipeEditorFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.CompanyJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
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.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class RecipeEditorController {
private RecipeJavaService recipeService;
private CompanyJavaService companyService;
@Autowired
public RecipeEditorController(RecipeJavaService recipeService, CompanyJavaService companyService) {
this.recipeService = recipeService;
this.companyService = companyService;
}
@GetMapping(EDITOR_RECIPE)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(EDITOR_RECIPE)
.addResponseData(ResponseDataType.RECIPE_MAP, recipeService.getAllMappedByCompany())
.build();
}
@GetMapping(EDITOR_RECIPE_SPECIFIC)
public ModelAndView getEditPage(ModelAndView model, @PathVariable Long id, Recipe recipe) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_RECIPE_EDITOR);
try {
if (recipe.getName() == null) recipe = recipeService.getById(id);
modelResponseBuilder
.addResponseData(ResponseDataType.RECIPE, recipe)
.addResponseData(ResponseDataType.COMPANIES, companyService.getAll())
.addResponseData(ResponseDataType.MIXES, recipe.getMixesSortedById())
.addResponseData(ResponseDataType.IMAGES, recipeService.getImageFiles(recipe))
.addResponseData(ResponseDataType.RECIPE_JSON, recipeService.asJson(recipe));
} catch (EntityNotFoundException ex) {
return getPage(modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id).build());
}
return modelResponseBuilder.build();
}
@PostMapping(value = EDITOR_RECIPE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@Transactional
public ModelAndView updateRecipe(RecipeEditorFormDto recipeDto) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
recipeService.updateRecipeAndSteps(recipeDto);
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_RECIPE, recipeDto.getRecipe().getName());
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, recipeDto.getRecipe().getId()).build();
}
return getPage(modelResponseBuilder.build());
}
}

View File

@ -1,83 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.files;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.web.response.JSONResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.service.files.ImagesService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import java.io.IOException;
import java.util.Map;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class ImageFilesController {
private RecipeJavaService recipeService;
private ImagesService imagesService;
@Autowired
public ImageFilesController(RecipeJavaService recipeService, ImagesService imagesService) {
this.recipeService = recipeService;
this.imagesService = imagesService;
}
@GetMapping(IMAGES_FILES)
public ResponseEntity<byte[]> getImage(@PathVariable String image) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<>(imagesService.read(image), headers, HttpStatus.OK);
}
@GetMapping(ADD_IMAGE_SPECIFIC)
public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
return new ModelResponseBuilder(model)
.withView(ADD_IMAGE)
.addResponseData(ResponseDataType.RECIPE_ID, id)
.build();
}
@PostMapping(ADD_IMAGE)
public ModelAndView addImage(Long id, MultipartFile image) throws IOException {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_RECIPE_SPECIFIC, id);
try {
if (!imagesService.isImage(image.getInputStream())) {
modelResponseBuilder.addResponseCode(ResponseCode.FILE_NOT_IMAGE);
} else {
Recipe recipe = recipeService.getById(id);
if (imagesService.write(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);
}
@GetMapping(value = DELETE_IMAGE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Map<String, Object> deleteImage(@PathVariable String image) {
imagesService.delete(image);
return new JSONResponseBuilder().build();
}
}

View File

@ -1,59 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.files;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.service.files.SimdutService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpServletRequest;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.CLOSE_TAB;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.SIMDUT_FILES;
@Controller
@Profile("thymeleaf")
public class SimdutFilesController {
private SimdutService simdutService;
@Autowired
public SimdutFilesController(SimdutService simdutService) {
this.simdutService = simdutService;
}
@GetMapping(SIMDUT_FILES)
public ResponseEntity<byte[]> getFile(HttpServletRequest request, @PathVariable Long id) {
HttpHeaders headers = new HttpHeaders();
try {
if (simdutService.exists(id)) {
byte[] simdutContent = simdutService.read(id);
headers.setContentType(MediaType.APPLICATION_PDF);
return new ResponseEntity<>(simdutContent, headers, HttpStatus.OK);
} else {
headers.add("Location", "/" + CLOSE_TAB);
}
} catch (EntityNotFoundException ex) {
headers.add("Location", request.getHeader("referer"));
}
return new ResponseEntity<>(headers, HttpStatus.FOUND);
}
@PostMapping(SIMDUT_FILES)
public ResponseEntity<Void> getFile(@PathVariable Long id) {
try {
return ResponseEntity.status(simdutService.exists(id) ? HttpStatus.OK : HttpStatus.NOT_FOUND).build();
} catch (EntityNotFoundException ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
}
}

View File

@ -1,52 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.files;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.service.files.TouchUpKitService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class TouchUpKitController {
private TouchUpKitService touchUpKitService;
private RecipeJavaService recipeService;
@Autowired
public TouchUpKitController(TouchUpKitService touchUpKitService, RecipeJavaService recipeService) {
this.touchUpKitService = touchUpKitService;
this.recipeService = recipeService;
}
@GetMapping(TOUCHUP)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(TOUCHUP)
.addResponseData(ResponseDataType.RECIPE_MAP, recipeService.getAllMappedByCompany())
.build();
}
@PostMapping(value = TOUCHUP_PDF, produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> getTouchUpKitPdf(String jobNumber) {
return new ResponseEntity<>(touchUpKitService.generatePdfForJobNumber(jobNumber), HttpStatus.FOUND);
}
@PostMapping(value = TOUCHUP_PTOUCH)
public ModelAndView getTouchUpKitPtouch(String jobNumber) {
return new ModelResponseBuilder(TOUCHUP_PTOUCH_PAGE)
.addAttribute("jobNumber", jobNumber)
.build();
}
}

View File

@ -1,63 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.files;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.service.files.XlsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.ALL_RECIPES_XLS;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.RECIPE_XLS;
@Controller
@Profile("thymeleaf")
public class XlsExporterController {
private XlsService xlsService;
@Autowired
public XlsExporterController(XlsService xlsService) {
this.xlsService = xlsService;
}
@GetMapping(RECIPE_XLS)
public ResponseEntity<byte[]> getXlsForRecipe(HttpServletRequest request, @PathVariable Long id) {
HttpHeaders headers = new HttpHeaders();
try {
byte[] xlsContent = xlsService.generate(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);
}
}
@GetMapping(value = ALL_RECIPES_XLS, produces = "application/zip")
public ResponseEntity<byte[]> getAllXls() throws IOException {
HttpHeaders headers = new HttpHeaders();
byte[] allXlsContent = xlsService.generateForAll();
return ResponseEntity.ok()
.headers(headers)
.contentLength(allXlsContent.length)
.contentType(MediaType.parseMediaType("application/zip"))
.body(allXlsContent);
}
}

View File

@ -1,56 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.removers;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityLinkedException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Company;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.service.model.CompanyJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_COMPANY;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_COMPANY_SPECIFIC;
@Controller
@Profile("thymeleaf")
public class CompanyRemoverController {
private CompanyJavaService companyService;
@Autowired
public CompanyRemoverController(CompanyJavaService companyService) {
this.companyService = companyService;
}
@GetMapping(REMOVER_COMPANY)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(REMOVER_COMPANY)
.addResponseData(ResponseDataType.COMPANIES, companyService.getAll())
.build();
}
@PostMapping(REMOVER_COMPANY_SPECIFIC)
public ModelAndView removeCompany(@PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder("");
try {
Company company = companyService.getById(id);
companyService.delete(company);
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_COMPANY, company.getName());
} catch (EntityLinkedException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_LINKED, companyService.getById(id).getName());
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.COMPANY_NOT_FOUND, id);
}
return getPage(modelResponseBuilder.build());
}
}

View File

@ -1,58 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.removers;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityLinkedException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.servlet.ModelAndView;
import java.util.stream.Collectors;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_MATERIAL;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_MATERIAL_SPECIFIC;
@Controller
@Profile("thymeleaf")
public class MaterialRemoverController {
private MaterialJavaService materialService;
@Autowired
public MaterialRemoverController(MaterialJavaService materialService) {
this.materialService = materialService;
}
@GetMapping(REMOVER_MATERIAL)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(REMOVER_MATERIAL)
.addResponseData(ResponseDataType.MATERIALS, materialService.getAll().stream().filter(m -> !m.isMixType()).collect(Collectors.toList()))
.build();
}
@PostMapping(REMOVER_MATERIAL_SPECIFIC)
public ModelAndView removeMaterial(@PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
Material material = materialService.getById(id);
materialService.delete(material);
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_MATERIAL, material.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(modelResponseBuilder.build());
}
}

View File

@ -1,60 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.removers;
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteDefaultMaterialTypeException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityLinkedException;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
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.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_MATERIAL_TYPE;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_MATERIAL_TYPE_SPECIFIC;
@Controller
@Profile("thymeleaf")
public class MaterialTypeRemoverController {
private MaterialTypeJavaService materialTypeService;
@Autowired
public MaterialTypeRemoverController(MaterialTypeJavaService materialTypeService) {
this.materialTypeService = materialTypeService;
}
@GetMapping(REMOVER_MATERIAL_TYPE)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(REMOVER_MATERIAL_TYPE)
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAllNotDefault())
.build();
}
@PostMapping(REMOVER_MATERIAL_TYPE_SPECIFIC)
public ModelAndView removeMaterialType(@PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
MaterialType materialType = materialTypeService.getById(id);
materialTypeService.delete(materialType);
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_MATERIAL_TYPE, materialType.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);
} catch (CannotDeleteDefaultMaterialTypeException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.CANNOT_REMOVE_DEFAULT_MATERIAL_TYPE);
}
return getPage(modelResponseBuilder.build());
}
}

View File

@ -1,44 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.removers;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixJavaService;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
@Controller
@Profile("thymeleaf")
public class MixRemoverController {
private MixJavaService mixService;
public MixRemoverController(MixJavaService mixService) {
this.mixService = mixService;
}
@GetMapping(REMOVER_MIX_SPECIFIC)
public ModelAndView removeMix(@PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
Mix mix = mixService.getById(id);
mixService.delete(mix);
return modelResponseBuilder
.withRedirect(EDITOR_RECIPE_SPECIFIC, mix.getRecipe().getId())
.build();
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id);
}
return modelResponseBuilder
.withRedirect(EDITOR_MIX_SPECIFIC, id)
.build();
}
}

View File

@ -1,51 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.removers;
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
import org.springframework.context.annotation.Profile;
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.servlet.ModelAndView;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_RECIPE;
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.REMOVER_RECIPE_SPECIFIC;
@Controller
@Profile("thymeleaf")
public class RecipeRemoverController {
private RecipeJavaService recipeService;
public RecipeRemoverController(RecipeJavaService recipeService) {
this.recipeService = recipeService;
}
@GetMapping(REMOVER_RECIPE)
public ModelAndView getPage(ModelAndView model) {
return new ModelResponseBuilder(model)
.withView(REMOVER_RECIPE)
.addResponseData(ResponseDataType.RECIPE_MAP, recipeService.getAllMappedByCompany())
.build();
}
@PostMapping(REMOVER_RECIPE_SPECIFIC)
public ModelAndView removeRecipe(@PathVariable Long id) {
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
try {
Recipe recipe = recipeService.getById(id);
recipeService.delete(recipe);
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_DELETING_RECIPE, recipe.getName());
} catch (EntityNotFoundException ex) {
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id);
}
return getPage(modelResponseBuilder.build());
}
}

View File

@ -1,25 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.response;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.HashMap;
import java.util.Map;
public class JSONResponseBuilder extends ResponseBuilder<JSONResponseBuilder, Map<String, Object>> {
@Override
protected void addResponseCodeToAttribute(String responseCodeType, String responseMessagePath, String[] parameters) {
Map<String, Object> attributeContent = new HashMap<>();
// Récupère le message depuis le fichier des messages de la bonne language et rajoute ces paramètres.
String message = Preferences.messageSource.getMessage(responseMessagePath, parameters, LocaleContextHolder.getLocale());
attributeContent.put("message", message);
addAttribute(responseCodeType, attributeContent);
}
public Map<String, Object> build() {
return attributes;
}
}

View File

@ -1,63 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.response;
import org.springframework.web.servlet.ModelAndView;
public class ModelResponseBuilder extends ResponseBuilder<ModelResponseBuilder, ModelAndView> {
private static final String PATH_PARAMETER_PATTERN = "(\\{\\w+\\})";
private static final String REDIRECT_PATH_PREFIX = "redirect:/";
private ModelAndView model;
public ModelResponseBuilder() {
this.model = new ModelAndView();
}
public ModelResponseBuilder(String view) {
this(new ModelAndView(view));
}
public ModelResponseBuilder(ModelAndView model) {
this.model = model == null ? new ModelAndView() : model;
}
public ModelResponseBuilder withView(String path) {
model.setViewName(path);
return this;
}
public ModelResponseBuilder withView(String path, Object... parameters) {
path = replaceInPath(path, parameters);
model.setViewName(path);
return this;
}
public ModelResponseBuilder withRedirect(String path, Object... parameters) {
return withView(REDIRECT_PATH_PREFIX + path, parameters);
}
@Override
protected void addResponseCodeToAttribute(String responseCodeType, String responseMessagePath, String[] parameters) {
addAttribute(responseCodeType, responseMessagePath);
for (int i = 0; i < parameters.length; i++) {
addAttribute(String.format("responseArg%s", i + 1), parameters[i]);
}
}
public ModelAndView build() {
model.addAllObjects(attributes);
return model;
}
private String replaceInPath(String path, Object... parameters) {
for (Object parameter : parameters) {
path = path.replaceFirst(PATH_PARAMETER_PATTERN, parameter.toString());
}
return path;
}
}

View File

@ -1,113 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.response;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import dev.fyloz.trial.colorrecipesexplorer.utils.ControllerUtils;
import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ResponseBuilder<T extends ResponseBuilder, R> {
protected static final String RESPONSE_PREFIX = "response.";
protected static final String ERROR_ATTRIBUTE_NAME = "error";
protected static final String SUCCESS_ATTRIBUTE_NAME = "success";
protected Map<String, Object> attributes;
private boolean containsErrors = false;
public ResponseBuilder() {
attributes = new HashMap<>();
// Ajoute l'URL de base à toutes les réponses
attributes.put("baseUrl", ControllerUtils.getCurrentBaseUrl());
attributes.put("referer", ControllerUtils.getLatestUrl());
}
protected abstract void addResponseCodeToAttribute(String responseCodeType, String responseMessagePath, String[] parameters);
protected abstract R build();
public T addResponseCode(ResponseCode responseCode, Object... parameters) {
String[] parametersAsStr = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parametersAsStr[i] = parameters[i].toString();
}
return addResponseCode(responseCode, parametersAsStr);
}
public T addResponseCode(ResponseCode responseCode, String... parameters) {
int requiredParametersNumber = responseCode.getParametersNumber();
int givenParametersNumber = parameters.length;
if (requiredParametersNumber != givenParametersNumber) {
throw new IllegalArgumentException(String.format("Mauvais nombre de paramètre dans une réponse de modèle: %s requis, %s fournis", requiredParametersNumber, givenParametersNumber));
}
// Ajoute les paramètres, si nécessaire
if (requiredParametersNumber > 0) {
// Avertit s'il y a plus de paramètres que le nombre de paramètres supporté par le template thymeleaf (aussi MAX_PARAMETERS_NUMBER)
int maxParametersNumber = ResponseCode.MAX_PARAMETERS_NUMBER;
if (givenParametersNumber > maxParametersNumber) {
Preferences.logger.warn(String.format("Trop de paramètres fournis pour le code de réponse %s: %s maximum, %s fournis", responseCode.name(), maxParametersNumber, givenParametersNumber));
}
}
String responseCodeType;
if (responseCode.getType() == ResponseCode.ResponseCodeType.ERROR) {
containsErrors = true;
responseCodeType = ERROR_ATTRIBUTE_NAME;
} else {
responseCodeType = SUCCESS_ATTRIBUTE_NAME;
}
String responseMessagePath = RESPONSE_PREFIX + responseCode.getCode();
addResponseCodeToAttribute(responseCodeType, responseMessagePath, parameters);
return (T) this;
}
public T addResponseData(ResponseDataType responseDataType, Object data) {
Class requiredDataTypeClass = responseDataType.getDataType();
Class requiredListDataTypeClass = responseDataType.getListDataType();
Class givenDataTypeClass = data.getClass();
// Vérifie le type de l'objet
if (!requiredDataTypeClass.equals(givenDataTypeClass)) {
throw new IllegalArgumentException(String.format("L'objet passé en paramètre n'est pas du bon type. Requis: %s, fournis: %s", requiredDataTypeClass.getName(), givenDataTypeClass.getName()));
}
// Si l'objet est une liste, vérifie qu'elle n'est pas vide et qu'elle est du bon type
if (requiredDataTypeClass.equals(List.class) && requiredListDataTypeClass != null) {
List listData = (List) data;
if (listData.size() < 1) {
throw new IllegalArgumentException("La liste passée en paramètre ne contient aucun élément");
}
Class givenListDataTypeClass = listData.get(0).getClass();
if (givenDataTypeClass.equals(requiredListDataTypeClass)) {
throw new IllegalArgumentException(String.format("La liste passée en paramètre contient des éléments du mauvais type. Requis: %s, fournis: %s", requiredListDataTypeClass.getName(), givenListDataTypeClass.getName()));
}
}
// Ajoute l'attribut dans le Map
addAttribute(responseDataType.getDataTypeName(), data);
return (T) this;
}
public T addAttribute(String attributeName, Object content) {
attributes.put(attributeName, content);
return (T) this;
}
public boolean containsErrors() {
return containsErrors;
}
}

View File

@ -1,78 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.response;
public enum ResponseCode {
SUCCESS_USING_MATERIALS(1, ResponseCodeType.SUCCESS, 0),
SUCCESS_SAVING_RECIPE_INFORMATIONS(2, ResponseCodeType.SUCCESS, 0),
ERROR_SAVING(3, ResponseCodeType.ERROR, 0),
ERROR_SAVING_IMAGE(4, ResponseCodeType.ERROR, 0),
ERROR_SAVING_SIMDUT(5, ResponseCodeType.ERROR, 0),
AUTH_ERROR(6, ResponseCodeType.ERROR, 0),
RECIPE_NOT_FOUND(7, ResponseCodeType.ERROR, 1),
MIX_NOT_FOUND(8, ResponseCodeType.ERROR, 1),
MATERIAL_NOT_FOUND(9, ResponseCodeType.ERROR, 1),
MATERIAL_ALREADY_EXIST(10, ResponseCodeType.ERROR, 1),
MATERIAL_TYPE_ALREADY_EXIST(11, ResponseCodeType.ERROR, 1),
COMPANY_NOT_FOUND(12, ResponseCodeType.ERROR, 1),
COMPANY_ALREADY_EXIST(13, ResponseCodeType.ERROR, 1),
MATERIAL_LINKED(14, ResponseCodeType.ERROR, 1),
COMPANY_LINKED(15, ResponseCodeType.ERROR, 1),
MIX_NOT_ASSOCIATED_WITH_RECIPE(16, ResponseCodeType.ERROR, 2),
NOT_ENOUGH_MATERIAL(17, ResponseCodeType.ERROR, 1),
MIX_TYPE_ALREADY_USED(18, ResponseCodeType.ERROR, 1),
MATERIAL_TYPE_NOT_FOUND(19, ResponseCodeType.ERROR, 1),
MATERIAL_TYPE_ALREADY_EXIST_PREFIX(20, ResponseCodeType.ERROR, 1),
MATERIAL_TYPE_LINKED(21, ResponseCodeType.ERROR, 1),
NO_COMPANY(22, ResponseCodeType.ERROR, 0),
NO_MATERIAL(23, ResponseCodeType.ERROR, 0),
FILE_NOT_IMAGE(24, ResponseCodeType.ERROR, 0),
RECIPE_NOT_FOUND_NO_PARAMS(25, ResponseCodeType.ERROR, 0),
MATERIAL_NOT_FOUND_BY_NAME(26, ResponseCodeType.ERROR, 1),
SUCCESS_DELETING_COMPANY(27, ResponseCodeType.SUCCESS, 1),
SUCCESS_SAVING_MATERIAL(28, ResponseCodeType.SUCCESS, 1),
SUCCESS_SAVING_MATERIAL_TYPE(29, ResponseCodeType.SUCCESS, 1),
SUCCESS_SAVING_RECIPE(30, ResponseCodeType.SUCCESS, 1),
SUCCESS_DELETING_MATERIAL(31, ResponseCodeType.SUCCESS, 1),
SUCCESS_SAVING_COMPANY(32, ResponseCodeType.SUCCESS, 1),
SUCCESS_DELETING_RECIPE(33, ResponseCodeType.SUCCESS, 1),
SUCCESS_DELETING_MATERIAL_TYPE(34, ResponseCodeType.SUCCESS, 1),
RECIPE_ALREADY_EXIST(35, ResponseCodeType.ERROR, 1),
CANNOT_REMOVE_DEFAULT_MATERIAL_TYPE(36, ResponseCodeType.ERROR, 0),
CANNOT_EDIT_DEFAULT_MATERIAL_TYPE(37, ResponseCodeType.ERROR, 0),
MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME(38, ResponseCodeType.ERROR, 0),
// HTTP Errors
_500(100, ResponseCodeType.ERROR, 0),
_404(101, ResponseCodeType.ERROR, 0),
_401(102, ResponseCodeType.ERROR, 0),
;
public static final int MAX_PARAMETERS_NUMBER = 2;
private int code;
private ResponseCodeType type;
private int parametersNumber;
ResponseCode(int code, ResponseCodeType type, int parametersNumber) {
this.code = code;
this.type = type;
this.parametersNumber = parametersNumber;
}
public int getCode() {
return code;
}
public ResponseCodeType getType() {
return type;
}
public int getParametersNumber() {
return parametersNumber;
}
public enum ResponseCodeType {
ERROR,
SUCCESS
}
}

View File

@ -1,92 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.web.response;
import dev.fyloz.trial.colorrecipesexplorer.model.*;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MaterialTypeEditorDto;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.stream.Stream;
public enum ResponseDataType {
MATERIAL("material", Material.class),
MATERIALS("materials", ArrayList.class, MATERIAL),
MATERIAL_ID("materialId", Long.class),
MATERIAL_CODE("materialCode", String.class),
MATERIALS_JSON("materialsJson", String.class),
MATERIAL_TYPE("materialType", MaterialType.class),
MATERIAL_TYPES("materialTypes", ArrayList.class, MATERIAL_TYPE),
MATERIAL_TYPE_NAME("materialTypeName", String.class),
MATERIAL_TYPE_DTO("materialTypeDto", MaterialTypeEditorDto.class),
RECIPE("recipe", Recipe.class),
RECIPES("recipes", ArrayList.class, RECIPE),
RECIPE_ID("recipeId", Long.class),
RECIPE_CODE("recipeCode", String.class),
RECIPE_MAP("recipeMap", HashMap.class),
RECIPE_JSON("recipeJson", String.class),
RECIPE_STEP("recipeStep", RecipeStep.class),
RECIPE_STEPS("recipeSteps", ArrayList.class, RECIPE_STEP),
MIX("mix", Mix.class),
MIXES("mixes", ArrayList.class, MIX),
MIX_ID("mixId", Long.class),
MIX_JSON("mixJson", String.class),
MIX_TYPE("mixType", MixType.class),
MIX_TYPES("mixTypes", ArrayList.class, MIX_TYPE),
MIX_QUANTITY("mixQuantity", MixMaterial.class),
MIX_QUANTITIES("mixQuantities", ArrayList.class, MIX_QUANTITY),
COMPANY("company", Company.class),
COMPANIES("companies", ArrayList.class, COMPANY),
COMPANY_ID("companyId", Long.class),
COMPANY_NAME("companyName", String.class),
IMAGE("image", String.class),
IMAGES("images", ArrayList.class, IMAGE),
BLOCK_BUTTON("blockButton", boolean.class);
private String dataTypeName;
private Class dataType;
private Class listDataType;
ResponseDataType(String dataTypeName, Class dataType) {
this(dataTypeName, dataType, null);
}
ResponseDataType(String dataTypeName, Class dataType, ResponseDataType listDataType) {
this.dataTypeName = dataTypeName;
this.dataType = dataType;
if (listDataType != null) {
this.listDataType = listDataType.getDataType();
}
}
public String getDataTypeName() {
return dataTypeName;
}
public Class getDataType() {
return dataType;
}
public Class getListDataType() {
return listDataType;
}
@Override
public String toString() {
return getDataTypeName();
}
public static ResponseDataType getModelDataTypeFromDataType(Class dataType) {
return Stream.of(values()).filter(r -> r.getDataType().equals(dataType)).findFirst().orElse(null);
}
}

View File

@ -1,6 +1,5 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
@ -14,17 +13,23 @@ import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.NoteCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.SectionTitleCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.TitleCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.util.Position;
import org.slf4j.Logger;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
public class XlsxExporter {
private Logger logger;
public XlsxExporter(Logger logger) {
this.logger = logger;
}
public byte[] generate(Recipe recipe) {
Preferences.logger.info(String.format("Génération du XLS de la couleur %s (%s)", recipe.getName(), recipe.getId()));
logger.info(String.format("Génération du XLS de la couleur %s (%s)", recipe.getName(), recipe.getId()));
Document document = new Document(recipe.getName());
Document document = new Document(recipe.getName(), logger);
Sheet sheet = document.getSheet();
registerCells(recipe, sheet);

View File

@ -1,10 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component;
import dev.fyloz.trial.colorrecipesexplorer.config.Preferences;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.builder.SheetBuilder;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbookType;
import org.slf4j.Logger;
public class Document extends XSSFWorkbook {
@ -12,9 +12,11 @@ public class Document extends XSSFWorkbook {
private static final XSSFWorkbookType WORKBOOK_TYPE = XSSFWorkbookType.XLSX;
private Sheet sheet;
private Logger logger;
public Document(String name) {
public Document(String name, Logger logger) {
super(WORKBOOK_TYPE);
this.logger = logger;
sheet = new Sheet(this, createSheet(name));
}
@ -23,7 +25,7 @@ public class Document extends XSSFWorkbook {
try {
new SheetBuilder(sheet).build();
} catch (InvalidCellTypeException e) {
Preferences.logger.error("Une erreur est survenue lors de la génération du document: " + e.getLocalizedMessage());
logger.error("Une erreur est survenue lors de la génération du document: " + e.getLocalizedMessage());
}
}

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CREProperties
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CreProperties
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
@ -8,7 +8,11 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.runApplication
@SpringBootApplication(exclude = [LiquibaseAutoConfiguration::class])
@EnableConfigurationProperties(MaterialTypeProperties::class, CREProperties::class, DatabaseUpdaterProperties::class)
@EnableConfigurationProperties(
MaterialTypeProperties::class,
CreProperties::class,
DatabaseUpdaterProperties::class
)
class ColorRecipesExplorerApplication
fun main() {

View File

@ -0,0 +1,19 @@
package dev.fyloz.trial.colorrecipesexplorer.config
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialTypeService
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.ApplicationListener
import org.springframework.context.annotation.Configuration
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
class InitialDataLoader(
private val materialTypeService: MaterialTypeService,
private val materialTypeProperties: MaterialTypeProperties
) : ApplicationListener<ApplicationReadyEvent> {
override fun onApplicationEvent(event: ApplicationReadyEvent) =
materialTypeService.saveSystemTypes(materialTypeProperties.systemTypes)
}

View File

@ -0,0 +1,13 @@
package dev.fyloz.trial.colorrecipesexplorer.config
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class SpringConfiguration {
@Bean
fun logger(): Logger = LoggerFactory.getLogger(ColorRecipesExplorerApplication::class.java)
}

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.config
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.trial.colorrecipesexplorer.model.Employee
import dev.fyloz.trial.colorrecipesexplorer.model.EmployeeLoginRequest
import dev.fyloz.trial.colorrecipesexplorer.model.EmployeePermission
@ -291,7 +291,7 @@ class JwtAuthorizationFilter(
private fun getAuthenticationToken(employeeId: String): UsernamePasswordAuthenticationToken? = try {
val employeeDetails = userDetailsService.loadUserByEmployeeId(employeeId.toLong(), false)
UsernamePasswordAuthenticationToken(employeeDetails.username, null, employeeDetails.authorities)
} catch (_: EntityNotFoundRestException) {
} catch (_: EntityNotFoundException) {
null
}
}

View File

@ -0,0 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.config.properties
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties(prefix = "cre.server")
class CreProperties {
var workingDirectory: String = "data"
}

View File

@ -1,31 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.exception
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException
import dev.fyloz.trial.colorrecipesexplorer.model.Model
class EntityAlreadyExistsException(
modelType: Class<out Model>,
val identifierType: IdentifierType,
val identifierName: String?,
val requestedId: Any
) : ModelException(modelType) {
constructor(modelType: Class<out Model>, identifierType: IdentifierType, requestedId: Any) : this(
modelType,
identifierType,
identifierType.name,
requestedId
)
constructor(exception: EntityAlreadyExistsException) : this(
exception.type,
exception.identifierType,
exception.identifierName,
exception.requestedId
)
}
class EntityNotFoundException(
modelType: Class<out Model>,
val identifierType: IdentifierType,
val requestedId: Any
) : ModelException(modelType)

View File

@ -1,8 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.exception
import com.fasterxml.jackson.annotation.JsonProperty
import dev.fyloz.trial.colorrecipesexplorer.exception.model.*
import dev.fyloz.trial.colorrecipesexplorer.model.Model
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import org.springframework.context.annotation.Profile
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
@ -26,7 +25,7 @@ abstract class RestException(val exceptionMessage: String, val httpStatus: HttpS
}
@ResponseStatus(HttpStatus.CONFLICT)
class EntityAlreadyExistsRestException(val value: Any) :
class EntityAlreadyExistsException(val value: Any) :
RestException("An entity with the given identifier already exists", HttpStatus.CONFLICT) {
@Suppress("unused")
override fun buildBody(): RestExceptionBody = object : RestExceptionBody() {
@ -35,7 +34,7 @@ class EntityAlreadyExistsRestException(val value: Any) :
}
@ResponseStatus(HttpStatus.NOT_FOUND)
class EntityNotFoundRestException(val value: Any) :
class EntityNotFoundException(val value: Any) :
RestException("An entity could not be found with the given identifier", HttpStatus.NOT_FOUND) {
@Suppress("unused")
override fun buildBody(): RestExceptionBody = object : RestExceptionBody() {
@ -44,7 +43,7 @@ class EntityNotFoundRestException(val value: Any) :
}
@ResponseStatus(HttpStatus.CONFLICT)
class CannotDeleteEntityRestException(val value: Long) :
class CannotDeleteEntityException(val value: Long) :
RestException(
"The entity with the given identifier could not be deleted because it is required by other entities",
HttpStatus.CONFLICT
@ -55,15 +54,22 @@ class CannotDeleteEntityRestException(val value: Long) :
}
}
@ResponseStatus
class SimdutWriteException(val material: Material) :
RestException(
"Could not write the SIMDUT file to disk",
HttpStatus.INTERNAL_SERVER_ERROR
) {
@Suppress("unused")
override fun buildBody(): RestExceptionBody = object : RestExceptionBody() {
val materialId = material.id
}
}
@ControllerAdvice
@Profile("rest")
class RestResponseEntityExceptionHandler : ResponseEntityExceptionHandler() {
@ExceptionHandler(ModelException::class)
fun handleModelExceptions(exception: ModelException, request: WebRequest): ResponseEntity<Any> {
return handleRestExceptions(exception.toRestException(), request)
}
@ExceptionHandler(RestException::class)
fun handleRestExceptions(exception: RestException, request: WebRequest): ResponseEntity<Any> {
return handleExceptionInternal(exception, exception.buildBody(), HttpHeaders(), exception.httpStatus, request)
@ -84,11 +90,3 @@ class RestResponseEntityExceptionHandler : ResponseEntityExceptionHandler() {
return ResponseEntity(errors, headers, status)
}
}
fun ModelException.toRestException(): RestException {
return when (this) {
is EntityAlreadyExistsException -> EntityAlreadyExistsRestException(requestedId)
is EntityNotFoundException -> EntityNotFoundRestException(requestedId)
else -> throw UnsupportedOperationException("Cannot convert ${this::class.simpleName} to REST exception")
}
}

View File

@ -2,9 +2,8 @@ package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.config.blacklistedJwtTokens
import dev.fyloz.trial.colorrecipesexplorer.config.defaultGroupCookieName
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundRestException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.model.validation.or
import dev.fyloz.trial.colorrecipesexplorer.repository.EmployeeGroupRepository
@ -109,7 +108,7 @@ class EmployeeServiceImpl(employeeRepository: EmployeeRepository, val passwordEn
override fun getById(id: Long, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): Employee =
super.getById(id).apply {
if (ignoreSystemUsers && isSystemUser || ignoreDefaultGroupUsers && isDefaultGroupUser) throw EntityNotFoundRestException(
if (ignoreSystemUsers && isSystemUser || ignoreDefaultGroupUsers && isDefaultGroupUser) throw EntityNotFoundException(
id
)
}
@ -138,7 +137,7 @@ class EmployeeServiceImpl(employeeRepository: EmployeeRepository, val passwordEn
override fun save(entity: Employee): Employee {
if (existsByFirstNameAndLastName(entity.firstName, entity.lastName))
throw EntityAlreadyExistsRestException("${entity.firstName} ${entity.lastName}")
throw EntityAlreadyExistsException("${entity.firstName} ${entity.lastName}")
return super<AbstractExternalModelService>.save(entity)
}
@ -188,7 +187,7 @@ class EmployeeServiceImpl(employeeRepository: EmployeeRepository, val passwordEn
override fun update(entity: Employee, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): Employee {
with(repository.findByFirstNameAndLastName(entity.firstName, entity.lastName)) {
if (this != null && id != entity.id)
throw EntityAlreadyExistsRestException("${entity.firstName} ${entity.lastName}")
throw EntityAlreadyExistsException("${entity.firstName} ${entity.lastName}")
}
return super<AbstractExternalModelService>.update(entity)
@ -270,7 +269,7 @@ class EmployeeGroupServiceImpl(
override fun getRequestDefaultGroup(request: HttpServletRequest): EmployeeGroup {
val defaultGroupCookie = WebUtils.getCookie(request, defaultGroupCookieName)
?: throw EntityNotFoundRestException("defaultGroup")
?: throw EntityNotFoundException("defaultGroup")
val defaultGroupUser = employeeService.getById(
defaultGroupCookie.value.toLong(),
ignoreDefaultGroupUsers = false,
@ -327,7 +326,7 @@ class EmployeeUserDetailsServiceImpl(
return loadUserByEmployeeId(username.toLong(), true)
} catch (ex: EntityNotFoundException) {
throw UsernameNotFoundException(username)
} catch (ex: EntityNotFoundRestException) {
} catch (ex: EntityNotFoundException) {
throw UsernameNotFoundException(username)
}
}

View File

@ -1,12 +1,12 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.trial.colorrecipesexplorer.model.Company
import dev.fyloz.trial.colorrecipesexplorer.model.CompanySaveDto
import dev.fyloz.trial.colorrecipesexplorer.model.CompanyUpdateDto
import dev.fyloz.trial.colorrecipesexplorer.model.company
import dev.fyloz.trial.colorrecipesexplorer.repository.CompanyRepository
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
interface CompanyService : ExternalNamedModelService<Company, CompanySaveDto, CompanyUpdateDto, CompanyRepository> {
@ -15,7 +15,10 @@ interface CompanyService : ExternalNamedModelService<Company, CompanySaveDto, Co
}
@Service
class CompanyServiceImpl(companyRepository: CompanyRepository, val recipeService: RecipeJavaService) :
class CompanyServiceImpl(
companyRepository: CompanyRepository,
@Lazy val recipeService: RecipeService
) :
AbstractExternalNamedModelService<Company, CompanySaveDto, CompanyUpdateDto, CompanyRepository>(companyRepository),
CompanyService {
override fun isLinkedToRecipes(company: Company): Boolean = recipeService.existsByCompany(company)
@ -33,7 +36,7 @@ class CompanyServiceImpl(companyRepository: CompanyRepository, val recipeService
}
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityRestException(id)
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}
}

View File

@ -1,44 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.TooLowQuantityException
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.dto.InventoryDto
import org.springframework.stereotype.Service
@Service
class InventoryService(val materialService: MaterialService) {
/**
* Use all materials in the given [mixes].
* @throws TooLowQuantityException When there is not enough stock for a material
*/
fun use(mixes: List<InventoryDto>) {
mixes.forEach { mix ->
val materials = mix.materialIds.toMaterials()
materials.forEachIndexed { index, material ->
val quantity = mix.quantities[index]
if (!material.hasEnoughStock(quantity))
throw TooLowQuantityException(mix.mixId, material, material.inventoryQuantity, quantity)
material.use(quantity)
}
}
}
/** Convert material ids to [Material]s. */
private fun List<Long>.toMaterials(): List<Material> {
return map { materialService.getById(it) }
}
/** Check if there is at least the given [quantity] in stock for a [Material]. */
private fun Material.hasEnoughStock(quantity: Float): Boolean {
return inventoryQuantity >= quantity
}
/** Use a given [Material], for the given [quantity]. */
private fun Material.use(quantity: Float) {
inventoryQuantity -= quantity
materialService.update(this)
}
}
//interface InventoryService {
// fun deduct(quantities: InventoryDeductDto)
// fun deduct(material: Material, quantity: Float)
//}

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MaterialRepository
import dev.fyloz.trial.colorrecipesexplorer.service.files.SimdutService
@ -93,7 +93,7 @@ class MaterialServiceImpl(
}
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityRestException(id)
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}
}

View File

@ -1,9 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.trial.colorrecipesexplorer.exception.RestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeSaveDto
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeUpdateDto
@ -47,7 +47,7 @@ class MaterialTypeServiceImpl(repository: MaterialTypeRepository, private val ma
override fun save(entity: MaterialType): MaterialType {
if (existsByPrefix(entity.prefix))
throw EntityAlreadyExistsRestException(entity.prefix)
throw EntityAlreadyExistsException(entity.prefix)
return super<AbstractExternalNamedModelService>.save(entity)
}
@ -68,14 +68,14 @@ class MaterialTypeServiceImpl(repository: MaterialTypeRepository, private val ma
override fun update(entity: MaterialType): MaterialType {
with(repository.findByPrefix(entity.prefix)) {
if (this != null && id != entity.id)
throw EntityAlreadyExistsRestException(entity.prefix)
throw EntityAlreadyExistsException(entity.prefix)
}
return super<AbstractExternalNamedModelService>.update(entity)
}
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityRestException(id)
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository
import org.springframework.context.annotation.Lazy
@ -113,7 +113,7 @@ class MixServiceImpl(
}
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityRestException(id)
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}
}

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MixTypeRepository
import org.springframework.context.annotation.Lazy
@ -39,11 +39,11 @@ class MixTypeServiceImpl(
repository.existsByNameAndMaterialType(name, materialType)
override fun getByMaterial(material: Material): MixType =
repository.findByMaterial(material) ?: throw EntityNotFoundRestException(material.name)
repository.findByMaterial(material) ?: throw EntityNotFoundException(material.name)
override fun getByNameAndMaterialType(name: String, materialType: MaterialType): MixType =
repository.findByNameAndMaterialType(name, materialType)
?: throw EntityNotFoundRestException("$name/${materialType.name}")
?: throw EntityNotFoundException("$name/${materialType.name}")
override fun getOrCreateForNameAndMaterialType(name: String, materialType: MaterialType): MixType =
if (existsByNameAndMaterialType(name, materialType))
@ -53,7 +53,7 @@ class MixTypeServiceImpl(
override fun save(entity: MixType): MixType {
if (materialService.existsByName(entity.name))
throw EntityAlreadyExistsRestException(entity.name)
throw EntityAlreadyExistsException(entity.name)
return super.save(entity)
}
@ -78,7 +78,7 @@ class MixTypeServiceImpl(
})
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityRestException(id)
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}
}

View File

@ -1,11 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.model.validation.isNotNullAndNotBlank
import dev.fyloz.trial.colorrecipesexplorer.model.validation.or
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository
import dev.fyloz.trial.colorrecipesexplorer.service.files.FilesService
import dev.fyloz.trial.colorrecipesexplorer.service.files.FileService
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import java.io.File
@ -134,12 +134,12 @@ interface RecipeImageService {
}
@Service
class RecipeImageServiceImpl(val recipeService: RecipeService, val filesService: FilesService) : RecipeImageService {
class RecipeImageServiceImpl(val recipeService: RecipeService, val fileService: FileService) : RecipeImageService {
override fun getByIdForRecipe(id: Long, recipeId: Long): ByteArray =
try {
filesService.readAsBytes(getPath(id, recipeId))
fileService.readAsBytes(getPath(id, recipeId))
} catch (ex: NoSuchFileException) {
throw EntityNotFoundRestException("$recipeId/$id")
throw EntityNotFoundException("$recipeId/$id")
}
override fun getAllIdsForRecipe(recipeId: Long): Collection<Long> {
@ -164,16 +164,16 @@ class RecipeImageServiceImpl(val recipeService: RecipeService, val filesService:
}
val nextAvailableId = getNextAvailableId()
filesService.write(image, getPath(nextAvailableId, recipeId))
fileService.write(image, getPath(nextAvailableId, recipeId))
return nextAvailableId
}
override fun delete(id: Long, recipeId: Long) =
filesService.delete(getPath(id, recipeId))
fileService.delete(getPath(id, recipeId))
/** Gets the images directory of the recipe with the given [recipeId]. */
fun getRecipeDirectory(recipeId: Long) = File(filesService.getPath("$RECIPE_IMAGES_DIRECTORY/$recipeId"))
fun getRecipeDirectory(recipeId: Long) = File(fileService.getPath("$RECIPE_IMAGES_DIRECTORY/$recipeId"))
/** Gets the file of the image with the given [recipeId] and [id]. */
fun getPath(id: Long, recipeId: Long): String = filesService.getPath("$RECIPE_IMAGES_DIRECTORY/$recipeId/$id")
fun getPath(id: Long, recipeId: Long): String = fileService.getPath("$RECIPE_IMAGES_DIRECTORY/$recipeId/$id")
}

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundRestException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.trial.colorrecipesexplorer.model.EntityDto
import dev.fyloz.trial.colorrecipesexplorer.model.Model
import dev.fyloz.trial.colorrecipesexplorer.model.NamedModel
@ -69,18 +69,18 @@ abstract class AbstractService<E, R : JpaRepository<E, *>>(override val reposito
abstract class AbstractModelService<E : Model, R : JpaRepository<E, Long>>(repository: R) :
AbstractService<E, R>(repository), ModelService<E, R> {
override fun existsById(id: Long): Boolean = repository.existsById(id)
override fun getById(id: Long): E = repository.findByIdOrNull(id) ?: throw EntityNotFoundRestException(id)
override fun getById(id: Long): E = repository.findByIdOrNull(id) ?: throw EntityNotFoundException(id)
override fun save(entity: E): E {
if (entity.id != null && existsById(entity.id!!))
throw EntityAlreadyExistsRestException(entity.id!!)
throw EntityAlreadyExistsException(entity.id!!)
return super.save(entity)
}
override fun update(entity: E): E {
assertId(entity.id)
if (!existsById(entity.id!!))
throw EntityNotFoundRestException(entity.id!!)
throw EntityNotFoundException(entity.id!!)
return super.update(entity)
}
@ -95,12 +95,12 @@ abstract class AbstractModelService<E : Model, R : JpaRepository<E, Long>>(repos
abstract class AbstractNamedModelService<E : NamedModel, R : NamedJpaRepository<E>>(repository: R) :
AbstractModelService<E, R>(repository), NamedModelService<E, R> {
override fun existsByName(name: String): Boolean = repository.existsByName(name)
override fun getByName(name: String): E = repository.findByName(name) ?: throw EntityNotFoundRestException(name)
override fun getByName(name: String): E = repository.findByName(name) ?: throw EntityNotFoundException(name)
override fun deleteByName(name: String) = repository.deleteByName(name)
override fun save(entity: E): E {
if (existsByName(entity.name))
throw EntityAlreadyExistsRestException(entity.name)
throw EntityAlreadyExistsException(entity.name)
return super.save(entity)
}
@ -109,7 +109,7 @@ abstract class AbstractNamedModelService<E : NamedModel, R : NamedJpaRepository<
assertName(entity.name)
with(repository.findByName(entity.name)) {
if (this != null && id != entity.id)
throw EntityAlreadyExistsRestException(entity.name)
throw EntityAlreadyExistsException(entity.name)
}
return super.update(entity)
}

View File

@ -0,0 +1,89 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CreProperties
import org.slf4j.Logger
import org.springframework.core.io.ResourceLoader
import org.springframework.stereotype.Service
import org.springframework.util.FileCopyUtils
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
@Service
class FileService(
private val resourcesLoader: ResourceLoader,
private val creProperties: CreProperties,
private val logger: Logger
) {
/** Reads the resource at the given [path] as a [String]. */
fun readResource(path: String): String = try {
resourcesLoader.getResource("classpath:$path").inputStream.use {
readInputStreamAsString(it)
}
} catch (ex: IOException) {
logger.error("Could not read resource", ex)
""
}
/** Reads the given [stream] as a [String]. */
fun readInputStreamAsString(stream: InputStream) = with(FileCopyUtils.copyToByteArray(stream)) {
String(this, StandardCharsets.UTF_8)
}
/** Reads the file at the given [path] as a [ByteArray]. */
fun readAsBytes(path: String) =
Files.readAllBytes(Paths.get(path))
/** Reads the file at the given [path] as a [List] of [String]. */
fun readAsStrings(path: String) =
Files.readAllLines(Paths.get(path))
/** Write the given [multipartFile] to the file at the given [path]. */
fun write(multipartFile: MultipartFile, path: String): Boolean =
if (multipartFile.size <= 0) true
else try {
multipartFile.transferTo(create(path).toPath())
true
} catch (ex: IOException) {
logger.error("Unable to write multipart file", ex)
false
}
/** Creates a new file at the given [path]. If the file already exists, nothing will be done. */
fun create(path: String) = withFileAt(path) {
if (!exists(path)) {
try {
Files.createDirectories(this.parentFile.toPath())
Files.createFile(this.toPath())
} catch (ex: IOException) {
logger.error("Unable to create file", ex)
}
}
this
}
/** Deletes the file at the given [path]. */
fun delete(path: String) = withFileAt(path) {
try {
if (exists(path)) Files.delete(this.toPath())
} catch (ex: IOException) {
logger.error("Unable to delete file", ex)
}
}
/** Checks if a file with the given [path] exists on the disk. */
fun exists(path: String): Boolean = withFileAt(path) {
this.exists() && this.isFile
}
/** Runs the given [block] in the context of a file with the given [path]. */
fun <T> withFileAt(path: String, block: File.() -> T) =
with(File(path)) { block() }
fun getPath(fileName: String): String =
"${creProperties.workingDirectory}/$fileName"
}

View File

@ -0,0 +1,64 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files
import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutWriteException
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialService
import org.slf4j.Logger
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import java.io.IOException
private const val SIMDUT_DIRECTORY = "simdut"
@Service
class SimdutService(
private val fileService: FileService,
@Lazy private val materialService: MaterialService,
private val logger: Logger
) {
/** Checks if the given [material] has a SIMDUT file. */
fun exists(material: Material) =
fileService.exists(getPath(material))
/** Reads the SIMDUT file of the given [material]. */
fun read(material: Material): ByteArray {
val path = getPath(material)
if (fileService.exists(path)) return ByteArray(0)
return try {
fileService.readAsBytes(path)
} catch (ex: IOException) {
logger.error("Could not read SIMDUT file", ex)
ByteArray(0)
}
}
/** Reads the SIMDUT file of the material with the given [id]. */
fun read(id: Long) =
read(materialService.getById(id))
/** Writes the given [simdut] file for the given [material] to the disk. */
fun write(material: Material, simdut: MultipartFile) {
if (!fileService.write(simdut, getPath(material)))
throw SimdutWriteException(material)
}
/** Updates the SIMDUT file of the given [material] with the given [simdut]. */
fun update(simdut: MultipartFile, material: Material) {
delete(material)
write(material, simdut)
}
/** Deletes the SIMDUT file of the given [material]. */
fun delete(material: Material) =
fileService.delete(getPath(material))
/** Gets the path of the SIMDUT file of the given [material]. */
fun getPath(material: Material) =
fileService.getPath("$SIMDUT_DIRECTORY/${getSimdutFileName(material)}")
/** Gets the name of the SIMDUT file of the given [material]. */
fun getSimdutFileName(material: Material) =
material.id.toString()
}

View File

@ -1,9 +0,0 @@
{
"properties": [
{
"name": "http.port",
"type": "java.lang.String",
"description": "Port HTTP."
}
]
}

View File

@ -1 +0,0 @@
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration

View File

@ -1,3 +0,0 @@
spring.resources.static-locations=classpath:/thymeleaf/static/
spring.thymeleaf.prefix=classpath:/thymeleaf/templates/
spring.thymeleaf.suffix=.html

View File

@ -1,10 +1,7 @@
# PORT
server.port=9090
# CRE
cre.server.upload-directory=data
cre.server.password-file=passwords.txt
cre.server.url-use-port=true
cre.server.url-use-https=false
cre.server.working-directory=data
cre.security.jwt-secret=CtnvGQjgZ44A1fh295gE
cre.security.jwt-duration=18000000
# Root user

View File

@ -1,118 +0,0 @@
app.title=Color recipes explorer
company.add.title=Add a banner
company.delete.title=Delete banners
company.error.anyFound=No banners were found.
company.form.companyName=Banner name
company.success.created=The banner {0} has been saved.
company.success.deleted=The banner {0} has been deleted.
error.serverError=An error occurred while sending data to the server.
footer.lang=Voir en français
image.add.title=Add an image
inventory.askUseMix=Do you really want to deduct this mix from the inventory?
inventory.askUseRecipe=Do you really want to deduct this recipe from the inventory?
inventory.hideOthers=Hide other materials
inventory.lowQuantity=Low quantity
inventory.showOnly=Show only
keyword.back=Back
keyword.calculation=Calculation
keyword.cancel=Cancel
keyword.characters=characters
keyword.company=Banner
keyword.continue=Continue
keyword.delete=Delete
keyword.edit=Edit
keyword.id=ID
keyword.images=Images
keyword.material=Material
keyword.pdf=PDF
keyword.print=Print
keyword.ptouch=P-touch
keyword.ptouchTemplate=P-touch templates
keyword.quantity=Quantity
keyword.recipe=Recipe
keyword.remove=Remove
keyword.save=Save
keyword.search=Search
keyword.see=See
keyword.type=Type
keyword.units=Units
keyword.updates=Updates history
keyword.use=Use
material.add.title=Add a material
material.code=Code
material.delete.title=Delete materials
material.edit.title=Edit materials
material.editing.title=Editing {0}
material.error.anyFound=No materials were found.
material.inventoryQuantity=Inventory quantity
material.simdut.choose=Choose material's SIMDUT file
material.simdut.error.notFound=No SIMDUT file found
material.simdut=SIMDUT File
material.success.created=The material {0} has been saved.
material.success.deleted=The material {0} has been deleted.
material.success.saved=The material {0} has been saved.
material.type=Material type
materialType.add.title=Add a material type
materialType.delete.title=Delete material types
materialType.editing.title=Editing {0}
materialType.editor.title=Edit material types
materialType.error.anyFound=Any material type has been found.
materialType.name=Name
materialType.prefix=Prefix
materialType.success.deleted=The material type {0} has been deleted.
materialType.success.saved=The material type {0} has been saved.
materialType.usePercents=Use percentages
menu.add=Add
menu.delete=Delete
menu.edit=Edit
menu.explore=Explore
menu.inventory=Inventory
menu.others=Others
mix.add.subtitle=Add a mix for the recipe {0}
mix.add.title=Add a banner
mix.edit.subtitle=Editing a mix for the recipe {0} ({1})
mix.edit.title=Editing a mix
mix.location=Location
mix.mixType=Mix type
password.ask=What is your password?
password.notValid=Your password is not valid
recipe.add.title=Add a recipe
recipe.approbationDate=Approbation date
recipe.color=Color
recipe.delete.title=Delete recipes
recipe.description=Description
recipe.edit.addImage=Add an image
recipe.edit.addMix=Add a mix
recipe.edit.title=Edit a recipe
recipe.editing.title=Editing {0}
recipe.error.anyFound=No recipes were found.
recipe.explore.title={0} color
recipe.exportAllXLS=Export all colors (XLSX)
recipe.image.corrupted=Image deleted or corrupted
recipe.notice=Notice
recipe.print.confirm=Are you sure you want to print this mix?
recipe.print.error.bpacNotInstalled=BPac is not installed
recipe.print.error.noBase=There is no base in this mix
recipe.print.error=An error occurred while printing
recipe.print.printing=Printing in progress. This may take a few seconds.
recipe.print.status.error=The b-Pac extension is not installed
recipe.print.status.ok=The b-Pac extension is installed
recipe.remark=Remark
recipe.sample=Sample
recipe.steps=Steps
recipe.success.deleted=The recipe {0} has been deleted.
recipe.success.edit=The recipe {0} has been saved.
recipe.sucess.saved=The recipe {0} has been saved. You can now add ingredients.
recipe.touchup.title=Touch-up kit labels
recipe.touchup=Touch-up kit labels
recipe.warning.changesNotSaved=Changes are not saved
recipe.warning.exportAll=Do you really want to export all the colors? This can take some times and slow down the application.
recipe.warning.notApproved.short=Not approved
recipe.warning.notApproved=This recipe is not approved
recipe.xlsVersion=XLSX version
units.gallons=Gallons
units.liters=Liters
units.milliliters=Milliliters
warning.askChangePage=Are you sure you want to continue? Unsaved changes will be lost.
warning.noResult=Search returned no results
keyword.jobNumber=Job number

View File

@ -1,118 +0,0 @@
app.title=Explorateur de recettes de couleur
company.add.title=Ajout d'une bannière
company.delete.title=Supprimer des bannières
company.error.anyFound=Aucune bannière n'a été trouvée.
company.form.companyName=Nom de la bannière
company.success.created=La bannière {0} à été enregistrée.
company.success.deleted=La bannière {0} a bien été supprimée.
error.serverError=Une erreur est survenue lors de l'envoie des informations vers le serveur.
footer.lang=See in english
image.add.title=Ajout une image
inventory.askUseMix=Êtes-vous certain de vouloir déduire ce mélange de l'inventaire?
inventory.askUseRecipe=Êtes-vous certain de vouloir déduire cette recette de l'inventaire?
inventory.hideOthers=Cacher les autres produits
inventory.lowQuantity=Quantité faible
inventory.showOnly=Voir seulement
keyword.back=Retour
keyword.calculation=Calcul
keyword.cancel=Annuler
keyword.characters=caractères
keyword.company=Bannière
keyword.continue=Continuer
keyword.delete=Supprimer
keyword.edit=Modifier
keyword.id=Identifiant
keyword.images=Images
keyword.material=Produit
keyword.pdf=PDF
keyword.print=Imprimer
keyword.ptouch=P-touch
keyword.ptouchTemplate=Modèles P-touch
keyword.quantity=Quantité
keyword.recipe=Recette
keyword.remove=Retirer
keyword.save=Enregistrer
keyword.search=Rechercher
keyword.see=Voir
keyword.type=Type
keyword.units=Unités
keyword.updates=Historique des mises à jour
keyword.use=Utiliser
material.add.title=Ajout d'un produit
material.code=Code
material.delete.title=Supprimer des produits
material.edit.title=Modifer des produits
material.editing.title=Modification de {0}
material.error.anyFound=Aucun produit n'a été trouvé.
material.inventoryQuantity=Quantité en inventaire
material.simdut.choose=Choisissez le fichier SIMDUT du produit
material.simdut.error.notFound=Aucun fichier SIMDUT trouvé
material.simdut=Fichier SIMDUT
material.success.created=Le produit {0} a été enregistré.
material.success.deleted=Le produit {0} a bien été supprimée.
material.success.saved=Le produit {0} a bien été sauvegardé.
material.type=Type de produit
materialType.add.title=Ajout d'un type de produit
materialType.delete.title=Supprimer des types de produit
materialType.editing.title=Modification de {0}
materialType.editor.title=Modifier un type de produit
materialType.error.anyFound=Aucun type de produit n'a été trouvé.
materialType.name=Nom
materialType.prefix=Préfix
materialType.success.deleted=Le type de produit {0} a bien été supprimé.
materialType.success.saved=Le type de produit {0} a bien été sauvegardé.
materialType.usePercents=Utiliser les pourcentages
menu.add=Ajouter
menu.delete=Supprimer
menu.edit=Modifier
menu.explore=Explorer
menu.inventory=Inventaire
menu.others=Autres
mix.add.subtitle=Ajout d''un mélange pour la recette {0}
mix.add.title=Ajout d'un mélange
mix.edit.subtitle=Modifier un mélange pour la recette {0} ({1})
mix.edit.title=Modifier un mélange
mix.location=Position
mix.mixType=Type de mélange
password.ask=Quel est votre mot de passe?
password.notValid=Votre mot de passe n'est pas valide
recipe.add.title=Ajout d'une recette
recipe.approbationDate=Date d'approbation
recipe.color=Couleur
recipe.delete.title=Supprimer des recettes
recipe.description=Description
recipe.edit.addImage=Ajouter une image
recipe.edit.addMix=Ajouter un mélange
recipe.edit.title=Modifier une recette
recipe.editing.title=Modification de {0}
recipe.error.anyFound=Aucune recette n'a été trouvée.
recipe.explore.title=Couleur {0}
recipe.exportAllXLS=Exporter toutes les couleurs (XLSX)
recipe.image.corrupted=Image supprimée ou corrompue
recipe.notice=Note
recipe.print.confirm=Voulez-vous vraiment imprimer ce mélange?
recipe.print.error.bpacNotInstalled=BPac n'est pas installé
recipe.print.error.noBase=Il n'y a pas de base dans ce mélange
recipe.print.error=Une erreur est survenue pendant l'impression
recipe.print.printing=Impression en cours. Cette opération peut prendre quelques secondes.
recipe.print.status.error=L'extension b-Pac n'est pas installée
recipe.print.status.ok=L'extension b-Pac est installée
recipe.remark=Remarque
recipe.sample=Échantillon
recipe.steps=Étapes
recipe.success.deleted=La recette {0} a bien été supprimée.
recipe.success.edit=La recette {0} a bien été sauvegardée.
recipe.sucess.saved=La recette {0} à été enregistrée. Vous pouvez maintenant ajouter les ingrédients.
recipe.touchup.title=Étiquettes de kit de retouche
recipe.touchup=Étiquettes de kit de retouche
recipe.warning.changesNotSaved=Des modifications ne sont pas sauvegardées
recipe.warning.exportAll=Voulez-vous vraiment exporter toutes les couleurs? Cela peut prendre un certain temps et ralentir l'application.
recipe.warning.notApproved.short=Non approuvée
recipe.warning.notApproved=Cette recette n'est pas approuvée
recipe.xlsVersion=Version XLSX
units.gallons=Gallons
units.liters=Litres
units.milliliters=Millilitres
warning.askChangePage=Êtes-vous sûr de vouloir continuer? Les modifications non enregistrées seront perdues.
warning.noResult=La recherche n'a donné aucun résultat
keyword.jobNumber=Numéro de job

Some files were not shown because too many files have changed in this diff Show More