Merge branch 'model-modifications' into 'master'

Ajout des informations de groupe et des positions des étapes et ingrédients

Closes #48, #52, #40, #24, and #19

See merge request color-recipes-explorer/backend!20
This commit is contained in:
William Nolin 2021-03-30 00:53:06 +00:00
commit c0574cfa0e
94 changed files with 1033 additions and 908 deletions

View File

@ -1,4 +1,4 @@
group = "dev.fyloz.trial.colorrecipesexplorer"
group = "dev.fyloz.colorrecipesexplorer"
plugins {
id("java")
@ -28,7 +28,7 @@ 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("dev.fyloz.colorrecipesexplorer:database-manager:1.1.0")
implementation("dev.fyloz.colorrecipesexplorer:database-manager:1.2.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")

View File

@ -1,6 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
package dev.fyloz.colorrecipesexplorer.service.files;
import dev.fyloz.trial.colorrecipesexplorer.utils.PdfBuilder;
import dev.fyloz.colorrecipesexplorer.utils.PdfBuilder;
import dev.fyloz.colorrecipesexplorer.utils.PdfBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

View File

@ -1,8 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files;
package dev.fyloz.colorrecipesexplorer.service.files;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.service.RecipeService;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.XlsxExporter;
import dev.fyloz.colorrecipesexplorer.model.Recipe;
import dev.fyloz.colorrecipesexplorer.service.RecipeService;
import dev.fyloz.colorrecipesexplorer.xlsx.XlsxExporter;
import dev.fyloz.colorrecipesexplorer.model.Recipe;
import dev.fyloz.colorrecipesexplorer.service.RecipeService;
import dev.fyloz.colorrecipesexplorer.xlsx.XlsxExporter;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.utils;
package dev.fyloz.colorrecipesexplorer.utils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

View File

@ -1,18 +1,25 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx;
package dev.fyloz.colorrecipesexplorer.xlsx;
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeStep;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Catalog;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Table;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.DescriptionCell;
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 dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Table;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.DescriptionCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.SectionTitleCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.TitleCell;
import dev.fyloz.colorrecipesexplorer.xlsx.util.Position;
import dev.fyloz.colorrecipesexplorer.model.Mix;
import dev.fyloz.colorrecipesexplorer.model.MixMaterial;
import dev.fyloz.colorrecipesexplorer.model.Recipe;
import dev.fyloz.colorrecipesexplorer.model.RecipeStep;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Catalog;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Table;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.DescriptionCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.NoteCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.SectionTitleCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.TitleCell;
import dev.fyloz.colorrecipesexplorer.xlsx.util.Position;
import org.slf4j.Logger;
import java.io.ByteArrayOutputStream;
@ -84,23 +91,24 @@ public class XlsxExporter {
}
}
// Étapes
Collection<RecipeStep> steps = recipe.getSteps();
if (steps.size() > 0) {
sheet.registerCell(new SectionTitleCell("Étapes"));
Catalog stepsCatalog = new Catalog();
for (RecipeStep step : recipe.getSteps()) stepsCatalog.addContent(step.getMessage());
sheet.registerAllCells(stepsCatalog.getCells());
}
// Note
String note = recipe.getNote();
if (note != null) {
sheet.registerCell(new SectionTitleCell("Note"));
sheet.registerCell(new NoteCell(recipe.getNote()));
}
// Étapes TODO
throw new UnsupportedOperationException();
// Collection<RecipeStep> steps = recipe.getSteps();
// if (steps.size() > 0) {
// sheet.registerCell(new SectionTitleCell("Étapes"));
// Catalog stepsCatalog = new Catalog();
//
// for (RecipeStep step : recipe.getSteps()) stepsCatalog.addContent(step.getMessage());
//
// sheet.registerAllCells(stepsCatalog.getCells());
// }
//
// // Note
// String note = recipe.getNote();
// if (note != null) {
// sheet.registerCell(new SectionTitleCell("Note"));
// sheet.registerCell(new NoteCell(recipe.getNote()));
// }
}
}

View File

@ -1,10 +1,15 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.builder;
package dev.fyloz.colorrecipesexplorer.xlsx.builder;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;

View File

@ -1,11 +1,16 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.builder;
package dev.fyloz.colorrecipesexplorer.xlsx.builder;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.util.CellUtils;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.colorrecipesexplorer.xlsx.util.CellUtils;
import org.apache.poi.ss.util.CellRangeAddress;
public class SheetBuilder {

View File

@ -1,8 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component;
package dev.fyloz.colorrecipesexplorer.xlsx.component;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import org.apache.poi.ss.usermodel.CellType;
import java.util.ArrayList;

View File

@ -1,7 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component;
package dev.fyloz.colorrecipesexplorer.xlsx.component;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.builder.SheetBuilder;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import dev.fyloz.colorrecipesexplorer.xlsx.builder.SheetBuilder;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.InvalidCellTypeException;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbookType;
import org.slf4j.Logger;

View File

@ -1,6 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component;
package dev.fyloz.colorrecipesexplorer.xlsx.component;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;

View File

@ -1,11 +1,16 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component;
package dev.fyloz.colorrecipesexplorer.xlsx.component;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.exception.IndexOutOfTableBoundsException;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.util.Position;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.IndexOutOfTableBoundsException;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.Cell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.exception.IndexOutOfTableBoundsException;
import dev.fyloz.colorrecipesexplorer.xlsx.util.Position;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.IndexedColors;

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells;
import org.apache.poi.ss.usermodel.CellType;

View File

@ -1,8 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.IndexedColors;

View File

@ -1,8 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import org.apache.poi.ss.usermodel.CellType;
public class NoteCell extends Cell implements IBiggerCell, IFontCell {

View File

@ -1,9 +1,12 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.IndexedColors;

View File

@ -1,9 +1,12 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Document;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IBiggerCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IColoredCell;
import dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles.IFontCell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.IndexedColors;

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles;
public interface IBiggerCell {
int getWidth();

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles;
import org.apache.poi.ss.usermodel.IndexedColors;

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.component.cells.styles;
package dev.fyloz.colorrecipesexplorer.xlsx.component.cells.styles;
import org.apache.poi.ss.usermodel.IndexedColors;

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.exception;
package dev.fyloz.colorrecipesexplorer.xlsx.exception;
public class IndexOutOfTableBoundsException extends RuntimeException {

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.exception;
package dev.fyloz.colorrecipesexplorer.xlsx.exception;
import org.apache.poi.ss.usermodel.CellType;

View File

@ -1,6 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.util;
package dev.fyloz.colorrecipesexplorer.xlsx.util;
import dev.fyloz.trial.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Sheet;
import dev.fyloz.colorrecipesexplorer.xlsx.component.Sheet;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.xlsx.util;
package dev.fyloz.colorrecipesexplorer.xlsx.util;
import java.util.Objects;

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer
package dev.fyloz.colorrecipesexplorer
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CreProperties
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.colorrecipesexplorer.config.properties.CreProperties
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
import org.springframework.boot.context.properties.EnableConfigurationProperties

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer
package dev.fyloz.colorrecipesexplorer
import dev.fyloz.colorrecipesexplorer.databasemanager.CreDatabase
import dev.fyloz.colorrecipesexplorer.databasemanager.databaseContext
@ -11,7 +11,7 @@ import org.springframework.context.annotation.Configuration
import org.springframework.core.env.Environment
import javax.sql.DataSource
const val SUPPORTED_DATABASE_VERSION = 3
const val SUPPORTED_DATABASE_VERSION = 4
const val ENV_VAR_ENABLE_DATABASE_UPDATE_NAME = "CRE_ENABLE_DB_UPDATE"
val DATABASE_NAME_REGEX = Regex("(\\w+)$")

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.config
package dev.fyloz.colorrecipesexplorer.config
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialTypeService
import dev.fyloz.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.colorrecipesexplorer.service.MaterialTypeService
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.ApplicationListener
import org.springframework.context.annotation.Configuration

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.config
package dev.fyloz.colorrecipesexplorer.config
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication
import dev.fyloz.colorrecipesexplorer.ColorRecipesExplorerApplication
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.annotation.Bean

View File

@ -1,13 +1,13 @@
package dev.fyloz.trial.colorrecipesexplorer.config
package dev.fyloz.colorrecipesexplorer.config
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
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
import dev.fyloz.trial.colorrecipesexplorer.service.EmployeeService
import dev.fyloz.trial.colorrecipesexplorer.service.EmployeeServiceImpl
import dev.fyloz.trial.colorrecipesexplorer.service.EmployeeUserDetailsServiceImpl
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.Employee
import dev.fyloz.colorrecipesexplorer.model.EmployeeLoginRequest
import dev.fyloz.colorrecipesexplorer.model.EmployeePermission
import dev.fyloz.colorrecipesexplorer.service.EmployeeService
import dev.fyloz.colorrecipesexplorer.service.EmployeeServiceImpl
import dev.fyloz.colorrecipesexplorer.service.EmployeeUserDetailsServiceImpl
import io.jsonwebtoken.ExpiredJwtException
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.config.properties
package dev.fyloz.colorrecipesexplorer.config.properties
import org.springframework.boot.context.properties.ConfigurationProperties

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.config.properties
package dev.fyloz.colorrecipesexplorer.config.properties
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.trial.colorrecipesexplorer.model.materialType
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.materialType
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component
import org.springframework.util.Assert
@ -13,9 +13,9 @@ class MaterialTypeProperties {
var baseName: String = ""
data class MaterialTypeProperty(
var name: String = "",
var prefix: String = "",
var usePercentages: Boolean = false
var name: String = "",
var prefix: String = "",
var usePercentages: Boolean = false
) {
fun toMaterialType(): MaterialType {
Assert.hasText(name, "A system material type has an empty name")

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.exception
package dev.fyloz.colorrecipesexplorer.exception
import com.fasterxml.jackson.annotation.JsonProperty
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialQuantityDto
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.model.MaterialQuantityDto
import org.springframework.context.annotation.Profile
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
@ -85,7 +85,6 @@ class LowQuantitiesException(val materialQuantities: Collection<MaterialQuantity
}
@ControllerAdvice
@Profile("rest")
class RestResponseEntityExceptionHandler : ResponseEntityExceptionHandler() {
@ExceptionHandler(RestException::class)
fun handleRestExceptions(exception: RestException, request: WebRequest): ResponseEntity<Any> {

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
import org.hibernate.annotations.Fetch
import org.hibernate.annotations.FetchMode
import org.springframework.security.core.GrantedAuthority
@ -10,12 +10,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import java.time.LocalDateTime
import java.util.*
import javax.persistence.*
import javax.validation.constraints.NotBlank
import javax.validation.constraints.NotNull
import javax.validation.constraints.Size
import kotlin.jvm.Transient
private const val EMPLOYEE_ID_NULL_MESSAGE = "Un numéro d'employé est requis"

View File

@ -0,0 +1,57 @@
package dev.fyloz.colorrecipesexplorer.model
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
import javax.persistence.*
import javax.validation.constraints.NotBlank
import javax.validation.constraints.NotNull
private const val COMPANY_ID_NULL_MESSAGE = "Un identifiant est requis"
private const val COMPANY_NAME_NULL_MESSAGE = "Un nom est requis"
@Entity
@Table(name = "company")
data class Company(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@Column(unique = true)
override val name: String
) : NamedModel
open class CompanySaveDto(
@field:NotBlank(message = COMPANY_NAME_NULL_MESSAGE)
val name: String
) : EntityDto<Company> {
override fun toEntity(): Company = Company(null, name)
}
open class CompanyUpdateDto(
@field:NotNull(message = COMPANY_ID_NULL_MESSAGE)
val id: Long,
@field:NullOrNotBlank(message = COMPANY_NAME_NULL_MESSAGE)
val name: String?
) : EntityDto<Company> {
override fun toEntity(): Company = Company(id, name ?: "")
}
// ==== DSL ====
fun company(
id: Long? = null,
name: String = "name",
op: Company.() -> Unit = {}
) = Company(id, name).apply(op)
fun companySaveDto(
name: String = "name",
op: CompanySaveDto.() -> Unit = {}
) = CompanySaveDto(name).apply(op)
fun companyUpdateDto(
id: Long = 0L,
name: String? = "name",
op: CompanyUpdateDto.() -> Unit = {}
) = CompanyUpdateDto(id, name).apply(op)

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrSize
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrSize
import org.springframework.web.multipart.MultipartFile
import javax.persistence.*
import javax.validation.constraints.Min
@ -18,8 +18,6 @@ private const val MATERIAL_QUANTITY_MATERIAL_NULL_MESSAGE = "Un produit est requ
private const val MATERIAL_QUANTITY_QUANTITY_NULL_MESSAGE = "Une quantité est requises"
private const val MATERIAL_QUANTITY_QUANTITY_NEGATIVE_MESSAGE = "La quantité doit être supérieure ou égale à 0"
// === Entities ===
@Entity
@Table(name = "material")
data class Material(
@ -50,13 +48,10 @@ open class MaterialSaveDto(
val inventoryQuantity: Float,
@field:NotNull(message = MATERIAL_TYPE_NULL_MESSAGE)
val materialType: MaterialType,
val materialTypeId: Long,
val simdutFile: MultipartFile? = null
) : EntityDto<Material> {
override fun toEntity(): Material = Material(null, name, inventoryQuantity, false, materialType)
fun toMaterial() = toEntity()
}
) : EntityDto<Material>
open class MaterialUpdateDto(
@field:NotNull(message = MATERIAL_ID_NULL_MESSAGE)
@ -68,15 +63,10 @@ open class MaterialUpdateDto(
@field:NullOrSize(min = 0, message = MATERIAL_INVENTORY_QUANTITY_NEGATIVE_MESSAGE)
val inventoryQuantity: Float?,
val materialType: MaterialType?,
val materialTypeId: Long?,
val simdutFile: MultipartFile? = null
) : EntityDto<Material> {
override fun toEntity(): Material = Material(
id, name ?: "", inventoryQuantity
?: Float.MIN_VALUE, false, materialType
)
}
) : EntityDto<Material>
data class MaterialQuantityDto(
@field:NotNull(message = MATERIAL_QUANTITY_MATERIAL_NULL_MESSAGE)
@ -110,19 +100,19 @@ fun material(
fun materialSaveDto(
name: String = "name",
inventoryQuantity: Float = 0f,
materialType: MaterialType = materialType(),
materialTypeId: Long = 0L,
simdutFile: MultipartFile? = null,
op: MaterialSaveDto.() -> Unit = {}
) = MaterialSaveDto(name, inventoryQuantity, materialType, simdutFile).apply(op)
) = MaterialSaveDto(name, inventoryQuantity, materialTypeId, simdutFile).apply(op)
fun materialUpdateDto(
id: Long = 0L,
name: String? = "name",
inventoryQuantity: Float? = 0f,
materialType: MaterialType? = materialType(),
materialTypeId: Long? = 0L,
simdutFile: MultipartFile? = null,
op: MaterialUpdateDto.() -> Unit = {}
) = MaterialUpdateDto(id, name, inventoryQuantity, materialType, simdutFile).apply(op)
) = MaterialUpdateDto(id, name, inventoryQuantity, materialTypeId, simdutFile).apply(op)
fun materialQuantityDto(
materialId: Long,

View File

@ -1,9 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrSize
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrSize
import org.hibernate.annotations.ColumnDefault
import java.util.*
import javax.persistence.*
import javax.validation.constraints.NotBlank
import javax.validation.constraints.NotNull
@ -14,8 +13,6 @@ private const val MATERIAL_TYPE_NAME_NULL_MESSAGE = "Un nom est requis"
private const val MATERIAL_TYPE_PREFIX_NULL_MESSAGE = "Un préfixe est requis"
private const val MATERIAL_TYPE_PREFIX_SIZE_MESSAGE = "Le préfixe doit faire exactement 3 caractères"
const val IDENTIFIER_PREFIX_NAME = "prefix"
@Entity
@Table(name = "material_type")
data class MaterialType(

View File

@ -1,8 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import com.fasterxml.jackson.annotation.JsonIgnore
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
import java.util.*
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
import javax.persistence.*
import javax.validation.constraints.Min
import javax.validation.constraints.NotBlank
@ -35,8 +34,9 @@ data class Mix(
@JoinColumn(name = "mix_type_id")
var mixType: MixType,
@OneToMany(cascade = [CascadeType.ALL], mappedBy = "mix")
var mixMaterials: MutableCollection<MixMaterial>,
@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "mix_id")
var mixMaterials: MutableSet<MixMaterial>,
) : Model
open class MixSaveDto(
@ -49,7 +49,7 @@ open class MixSaveDto(
@field:NotNull(message = MIX_MATERIAL_TYPE_NULL_MESSAGE)
val materialTypeId: Long,
val mixMaterials: Map<Long, Float>?
val mixMaterials: Set<MixMaterialDto>?
) : EntityDto<Mix> {
override fun toEntity(): Mix = throw UnsupportedOperationException()
}
@ -63,7 +63,7 @@ open class MixUpdateDto(
val materialTypeId: Long?,
val mixMaterials: Map<Long, Float>?
var mixMaterials: Set<MixMaterialDto>?
) : EntityDto<Mix> {
override fun toEntity(): Mix = throw UnsupportedOperationException()
}
@ -77,13 +77,20 @@ data class MixDeductDto(
val ratio: Float
)
data class MixLocationDto(
@field:NotNull(message = MIX_DEDUCT_MIX_ID_NULL_MESSAGE)
val mixId: Long,
val location: String?
)
// ==== DSL ====
fun mix(
id: Long? = null,
location: String? = "location",
recipe: Recipe = recipe(),
mixType: MixType = mixType(),
mixMaterials: MutableCollection<MixMaterial> = mutableListOf(),
mixMaterials: MutableSet<MixMaterial> = mutableSetOf(),
op: Mix.() -> Unit = {}
) = Mix(id, location, recipe, mixType, mixMaterials).apply(op)
@ -91,7 +98,7 @@ fun mixSaveDto(
name: String = "name",
recipeId: Long = 0L,
materialTypeId: Long = 0L,
mixMaterials: Map<Long, Float>? = mapOf(),
mixMaterials: Set<MixMaterialDto>? = setOf(),
op: MixSaveDto.() -> Unit = {}
) = MixSaveDto(name, recipeId, materialTypeId, mixMaterials).apply(op)
@ -99,7 +106,7 @@ fun mixUpdateDto(
id: Long = 0L,
name: String? = "name",
materialTypeId: Long? = 0L,
mixMaterials: Map<Long, Float>? = mapOf(),
mixMaterials: Set<MixMaterialDto>? = setOf(),
op: MixUpdateDto.() -> Unit = {}
) = MixUpdateDto(id, name, materialTypeId, mixMaterials).apply(op)
@ -108,3 +115,9 @@ fun mixRatio(
ratio: Float = 1f,
op: MixDeductDto.() -> Unit = {}
) = MixDeductDto(id, ratio).apply(op)
fun mixLocationDto(
mixId: Long = 0L,
location: String? = "location",
op: MixLocationDto.() -> Unit = {}
) = MixLocationDto(mixId, location).apply(op)

View File

@ -0,0 +1,52 @@
package dev.fyloz.colorrecipesexplorer.model
import javax.persistence.*
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
private const val MIX_MATERIAL_DTO_MATERIAL_ID_NULL_MESSAGE = "Un identifiant de produit est requis"
private const val MIX_MATERIAL_DTO_QUANTITY_NULL_MESSAGE = "Une quantité est requise"
private const val MIX_MATERIAL_DTO_QUANTITY_NEGATIVE_MESSAGE = "La quantité ne peut pas être négative"
@Entity
@Table(name = "mix_material")
data class MixMaterial(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@ManyToOne
@JoinColumn(name = "material_id")
val material: Material,
var quantity: Float,
var position: Int
) : Model
data class MixMaterialDto(
@field:NotNull(message = MIX_MATERIAL_DTO_MATERIAL_ID_NULL_MESSAGE)
val materialId: Long,
@field:NotNull(message = MIX_MATERIAL_DTO_QUANTITY_NULL_MESSAGE)
@field:Min(value = 0, message = MIX_MATERIAL_DTO_QUANTITY_NEGATIVE_MESSAGE)
val quantity: Float,
val position: Int
)
// ==== DSL ====
fun mixMaterial(
id: Long? = null,
material: Material = material(),
quantity: Float = 0f,
position: Int = 0,
op: MixMaterial.() -> Unit = {}
) = MixMaterial(id, material, quantity, position).apply(op)
fun mixMaterialDto(
materialId: Long = 0L,
quantity: Float = 0f,
position: Int = 0,
op: MixMaterialDto.() -> Unit = {}
) = MixMaterialDto(materialId, quantity, position).apply(op)

View File

@ -1,6 +1,5 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import java.util.*
import javax.persistence.*
const val IDENTIFIER_MATERIAL_NAME = "material"

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
/** The model of a stored entity. Each model should implements its own equals and hashCode methods to keep compatibility with the legacy Java and Thymeleaf code. */
interface Model {

View File

@ -1,10 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import com.fasterxml.jackson.annotation.JsonIgnore
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrSize
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrSize
import java.time.LocalDate
import java.util.*
import javax.persistence.*
import javax.validation.constraints.*
@ -14,10 +13,14 @@ private const val RECIPE_DESCRIPTION_NULL_MESSAGE = "Une description est requise
private const val RECIPE_COLOR_NULL_MESSAGE = "Une couleur est requise"
private const val RECIPE_GLOSS_NULL_MESSAGE = "Le lustre de la couleur est requis"
private const val RECIPE_GLOSS_OUTSIDE_RANGE_MESSAGE = "Le lustre doit être entre 0 et 100"
private const val RECIPE_SAMPLE_NULL_MESSAGE = "Un numéro d'échantillon est requis"
private const val RECIPE_SAMPLE_TOO_SMALL_MESSAGE = "Le numéro d'échantillon doit être supérieur ou égal à 0"
private const val RECIPE_COMPANY_NULL_MESSAGE = "Une bannière est requise"
private const val RECIPE_STEPS_DTO_GROUP_ID_NULL_MESSAGE = "Un identifiant de groupe est requis"
private const val RECIPE_STEPS_DTO_MESSAGES_NULL_MESSAGE = "Des messages sont requis"
private const val NOTE_GROUP_ID_NULL_MESSAGE = "Un identifiant de groupe est requis"
@Entity
@Table(name = "recipe")
data class Recipe(
@ -44,9 +47,6 @@ data class Recipe(
/** A remark given by the creator of the recipe. */
val remark: String,
/** A note that can be altered by anybody with view permissions to the recipe. */
var note: String,
@ManyToOne
@JoinColumn(name = "company_id")
val company: Company,
@ -54,24 +54,19 @@ data class Recipe(
@OneToMany(cascade = [CascadeType.ALL], mappedBy = "recipe")
val mixes: MutableList<Mix>,
@OneToMany(cascade = [CascadeType.ALL], mappedBy = "recipe")
var steps: List<RecipeStep>
@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "recipe_id")
val groupsInformation: Set<RecipeGroupInformation>
) : Model {
/** The mix types contained in this recipe. */
val mixTypes: Collection<MixType>
@JsonIgnore
get() = mixes.map { it.mixType }
fun groupInformationForGroup(groupId: Long) =
groupsInformation.firstOrNull { it.group.id == groupId }
}
data class RecipePublicDataDto(
@field:NotNull(message = RECIPE_ID_NULL_MESSAGE)
val id: Long,
val note: String?,
val mixesLocation: Map<Long, String>?
)
open class RecipeSaveDto(
@field:NotBlank(message = RECIPE_NAME_NULL_MESSAGE)
val name: String,
@ -133,9 +128,51 @@ open class RecipeUpdateDto(
val remark: String?,
val steps: List<RecipeStep>?
val steps: Set<RecipeStepsDto>?
) : EntityDto<Recipe>
@Entity
@Table(name = "recipe_group_information")
data class RecipeGroupInformation(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long?,
@ManyToOne
@JoinColumn(name = "group_id")
val group: EmployeeGroup,
var note: String?,
@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "recipe_group_information_id")
var steps: MutableSet<RecipeStep>?
)
data class RecipeStepsDto(
@field:NotNull(message = RECIPE_STEPS_DTO_GROUP_ID_NULL_MESSAGE)
val groupId: Long,
@field:NotNull(message = RECIPE_STEPS_DTO_MESSAGES_NULL_MESSAGE)
val steps: Set<RecipeStep>
)
data class RecipePublicDataDto(
@field:NotNull(message = RECIPE_ID_NULL_MESSAGE)
val recipeId: Long,
val notes: Set<NoteDto>?,
val mixesLocation: Set<MixLocationDto>?
)
data class NoteDto(
@field:NotNull(message = NOTE_GROUP_ID_NULL_MESSAGE)
val groupId: Long,
val content: String?
)
// ==== DSL ====
fun recipe(
id: Long? = null,
@ -146,19 +183,23 @@ fun recipe(
sample: Int? = -1,
approbationDate: LocalDate? = LocalDate.MIN,
remark: String = "remark",
note: String = "",
company: Company = company(),
mixes: MutableList<Mix> = mutableListOf(),
steps: List<RecipeStep> = listOf(),
groupsInformation: Set<RecipeGroupInformation> = setOf(),
op: Recipe.() -> Unit = {}
) = Recipe(id, name, description, color, gloss, sample, approbationDate, remark, note, company, mixes, steps).apply(op)
fun recipePublicDataDto(
id: Long = 0L,
note: String? = "note",
mixesLocation: Map<Long, String>? = mapOf(),
op: RecipePublicDataDto.() -> Unit = {}
) = RecipePublicDataDto(id, note, mixesLocation).apply(op)
) = Recipe(
id,
name,
description,
color,
gloss,
sample,
approbationDate,
remark,
company,
mixes,
groupsInformation
).apply(op)
fun recipeSaveDto(
name: String = "name",
@ -181,6 +222,27 @@ fun recipeUpdateDto(
sample: Int? = -1,
approbationDate: LocalDate? = LocalDate.MIN,
remark: String? = "remark",
steps: List<RecipeStep>? = listOf(),
steps: Set<RecipeStepsDto>? = setOf(),
op: RecipeUpdateDto.() -> Unit = {}
) = RecipeUpdateDto(id, name, description, color, gloss, sample, approbationDate, remark, steps).apply(op)
fun recipeGroupInformation(
id: Long? = null,
group: EmployeeGroup = employeeGroup(),
note: String? = null,
steps: MutableSet<RecipeStep>? = mutableSetOf(),
op: RecipeGroupInformation.() -> Unit = {}
) = RecipeGroupInformation(id, group, note, steps).apply(op)
fun recipePublicDataDto(
recipeId: Long = 0L,
notes: Set<NoteDto>? = null,
mixesLocation: Set<MixLocationDto>? = null,
op: RecipePublicDataDto.() -> Unit = {}
) = RecipePublicDataDto(recipeId, notes, mixesLocation).apply(op)
fun noteDto(
groupId: Long = 0L,
content: String? = "note",
op: NoteDto.() -> Unit = {}
) = NoteDto(groupId, content).apply(op)

View File

@ -1,7 +1,5 @@
package dev.fyloz.trial.colorrecipesexplorer.model
package dev.fyloz.colorrecipesexplorer.model
import com.fasterxml.jackson.annotation.JsonIgnore
import java.util.*
import javax.persistence.*
@Entity
@ -11,19 +9,15 @@ data class RecipeStep(
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@JsonIgnore
@ManyToOne
@JoinColumn(name = "recipe_id")
val recipe: Recipe?,
val position: Int,
val message: String
) : Model
// ==== DSL ====
fun recipeStep(
id: Long? = null,
recipe: Recipe? = recipe(),
position: Int = 0,
message: String = "message",
op: RecipeStep.() -> Unit = {}
) = RecipeStep(id, recipe, message).apply(op)
) = RecipeStep(id, position, message).apply(op)

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.model.validation
package dev.fyloz.colorrecipesexplorer.model.validation
import javax.validation.Constraint
import javax.validation.ConstraintValidator

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.model.validation
package dev.fyloz.colorrecipesexplorer.model.validation
import javax.validation.Constraint
import javax.validation.ConstraintValidator
@ -14,11 +14,11 @@ private const val MESSAGE = "must be null or have a correct length"
@MustBeDocumented
@Constraint(validatedBy = [NullOrSizeValidator::class])
annotation class NullOrSize(
val min: Long = MIN_SIZE,
val max: Long = MAX_SIZE,
val message: String = MESSAGE,
val groups: Array<KClass<*>> = [],
@Suppress("unused") val payload: Array<KClass<out Payload>> = []
val min: Long = MIN_SIZE,
val max: Long = MAX_SIZE,
val message: String = MESSAGE,
val groups: Array<KClass<*>> = [],
@Suppress("unused") val payload: Array<KClass<out Payload>> = []
)
class NullOrSizeValidator : ConstraintValidator<NullOrSize, Any> {

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Employee
import dev.fyloz.trial.colorrecipesexplorer.model.EmployeeGroup
import dev.fyloz.colorrecipesexplorer.model.Employee
import dev.fyloz.colorrecipesexplorer.model.EmployeeGroup
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Company
import dev.fyloz.colorrecipesexplorer.model.Company
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository
@ -13,7 +13,7 @@ interface MaterialRepository : NamedJpaRepository<Material> {
/** Updates the [inventoryQuantity] of the [Material] with the given [id]. */
@Modifying
@Query("update Material m set m.inventoryQuantity = :inventoryQuantity where m.id = :id")
@Query("UPDATE Material m SET m.inventoryQuantity = :inventoryQuantity WHERE m.id = :id")
fun updateInventoryQuantityById(id: Long, inventoryQuantity: Float)
@Query(

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.model.MixMaterial
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

View File

@ -1,14 +1,20 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
import dev.fyloz.colorrecipesexplorer.model.Mix
import dev.fyloz.colorrecipesexplorer.model.MixType
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
interface MixRepository : JpaRepository<Mix, Long> {
/** Finds all mixes with the given [mixType]. */
fun findAllByMixType(mixType: MixType): Collection<Mix>
/** Updates the [location] of the [Mix] with the given [id]. */
@Modifying
@Query("UPDATE Mix m SET m.location = :location WHERE m.id = :id")
fun updateLocationById(id: Long, location: String?)
@Query(
"""
select case when(count(mm.id) > 0) then false else true end

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.MixType
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository

View File

@ -1,7 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Company
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe
import dev.fyloz.colorrecipesexplorer.model.Company
import dev.fyloz.colorrecipesexplorer.model.Recipe
import org.springframework.data.jpa.repository.JpaRepository
interface RecipeRepository : JpaRepository<Recipe, Long> {

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeStep
import dev.fyloz.colorrecipesexplorer.model.RecipeStep
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.NamedModel
import dev.fyloz.colorrecipesexplorer.model.NamedModel
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.repository.NoRepositoryBean

View File

@ -1,9 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
package dev.fyloz.colorrecipesexplorer.rest
import dev.fyloz.trial.colorrecipesexplorer.service.EmployeeGroupServiceImpl
import dev.fyloz.trial.colorrecipesexplorer.service.EmployeeServiceImpl
import dev.fyloz.trial.colorrecipesexplorer.model.*
import org.springframework.context.annotation.Profile
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.service.EmployeeGroupServiceImpl
import dev.fyloz.colorrecipesexplorer.service.EmployeeServiceImpl
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
@ -17,7 +16,6 @@ private const val EMPLOYEE_GROUP_CONTROLLER_PATH = "api/employee/group"
@RestController
@RequestMapping(EMPLOYEE_CONTROLLER_PATH)
@Profile("rest")
class EmployeeController(employeeService: EmployeeServiceImpl) :
AbstractModelRestApiController<Employee, EmployeeSaveDto, EmployeeUpdateDto, EmployeeServiceImpl>(
employeeService,
@ -79,7 +77,6 @@ class EmployeeController(employeeService: EmployeeServiceImpl) :
@RestController
@RequestMapping(EMPLOYEE_GROUP_CONTROLLER_PATH)
@Profile("rest")
class GroupsController(groupService: EmployeeGroupServiceImpl) :
AbstractModelRestApiController<EmployeeGroup, EmployeeGroupSaveDto, EmployeeGroupUpdateDto, EmployeeGroupServiceImpl>(
groupService,

View File

@ -1,10 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
package dev.fyloz.colorrecipesexplorer.rest
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.service.CompanyService
import org.springframework.context.annotation.Profile
import dev.fyloz.colorrecipesexplorer.model.Company
import dev.fyloz.colorrecipesexplorer.model.CompanySaveDto
import dev.fyloz.colorrecipesexplorer.model.CompanyUpdateDto
import dev.fyloz.colorrecipesexplorer.service.CompanyService
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@ -12,7 +11,6 @@ private const val COMPANY_CONTROLLER_PATH = "api/company"
@RestController
@RequestMapping(COMPANY_CONTROLLER_PATH)
@Profile("rest")
class CompanyController(companyService: CompanyService) :
AbstractModelRestApiController<Company, CompanySaveDto, CompanyUpdateDto, CompanyService>(
companyService,

View File

@ -1,9 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
package dev.fyloz.colorrecipesexplorer.rest
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialQuantityDto
import dev.fyloz.trial.colorrecipesexplorer.model.MixDeductDto
import dev.fyloz.trial.colorrecipesexplorer.service.InventoryService
import org.springframework.context.annotation.Profile
import dev.fyloz.colorrecipesexplorer.model.MaterialQuantityDto
import dev.fyloz.colorrecipesexplorer.model.MixDeductDto
import dev.fyloz.colorrecipesexplorer.service.InventoryService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
@ -14,7 +13,6 @@ private const val INVENTORY_CONTROLLER_PATH = "api/inventory"
@RestController
@RequestMapping(INVENTORY_CONTROLLER_PATH)
@Profile("rest")
class InventoryController(
private val inventoryService: InventoryService
) {

View File

@ -1,9 +1,7 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
package dev.fyloz.colorrecipesexplorer.rest
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.service.InventoryService
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialService
import org.springframework.context.annotation.Profile
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.service.MaterialService
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
@ -16,7 +14,6 @@ private const val MATERIAL_CONTROLLER_PATH = "api/material"
@RestController
@RequestMapping(MATERIAL_CONTROLLER_PATH)
@Profile("rest")
class MaterialController(materialService: MaterialService) :
AbstractModelRestApiController<Material, MaterialSaveDto, MaterialUpdateDto, MaterialService>(
materialService,
@ -63,7 +60,7 @@ class MaterialController(materialService: MaterialService) :
materialSaveDto(
name = entity.name,
inventoryQuantity = entity.inventoryQuantity,
materialType = entity.materialType,
materialTypeId = entity.materialTypeId,
simdutFile = simdutFile
)
)
@ -79,7 +76,7 @@ class MaterialController(materialService: MaterialService) :
id = entity.id,
name = entity.name,
inventoryQuantity = entity.inventoryQuantity,
materialType = entity.materialType,
materialTypeId = entity.materialTypeId,
simdutFile = simdutFile
)
)

View File

@ -0,0 +1,19 @@
package dev.fyloz.colorrecipesexplorer.rest
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.MaterialTypeSaveDto
import dev.fyloz.colorrecipesexplorer.model.MaterialTypeUpdateDto
import dev.fyloz.colorrecipesexplorer.service.MaterialTypeService
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
private const val MATERIAL_TYPE_CONTROLLER_PATH = "api/materialtype"
@RestController
@RequestMapping(MATERIAL_TYPE_CONTROLLER_PATH)
class MaterialTypeController(materialTypeService: MaterialTypeService) :
AbstractModelRestApiController<MaterialType, MaterialTypeSaveDto, MaterialTypeUpdateDto, MaterialTypeService>(
materialTypeService,
MATERIAL_TYPE_CONTROLLER_PATH
)

View File

@ -1,9 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
package dev.fyloz.colorrecipesexplorer.rest
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.service.MixService
import dev.fyloz.trial.colorrecipesexplorer.service.RecipeImageService
import dev.fyloz.trial.colorrecipesexplorer.service.RecipeService
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.service.MixService
import dev.fyloz.colorrecipesexplorer.service.RecipeImageService
import dev.fyloz.colorrecipesexplorer.service.RecipeService
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity

View File

@ -1,9 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
package dev.fyloz.colorrecipesexplorer.rest
import dev.fyloz.trial.colorrecipesexplorer.model.EntityDto
import dev.fyloz.trial.colorrecipesexplorer.model.Model
import dev.fyloz.trial.colorrecipesexplorer.service.ExternalModelService
import dev.fyloz.trial.colorrecipesexplorer.service.ExternalService
import dev.fyloz.colorrecipesexplorer.model.EntityDto
import dev.fyloz.colorrecipesexplorer.model.Model
import dev.fyloz.colorrecipesexplorer.service.ExternalModelService
import dev.fyloz.colorrecipesexplorer.service.ExternalService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

View File

@ -1,14 +1,15 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.config.blacklistedJwtTokens
import dev.fyloz.trial.colorrecipesexplorer.config.defaultGroupCookieName
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.model.validation.or
import dev.fyloz.trial.colorrecipesexplorer.repository.EmployeeGroupRepository
import dev.fyloz.trial.colorrecipesexplorer.repository.EmployeeRepository
import dev.fyloz.colorrecipesexplorer.config.blacklistedJwtTokens
import dev.fyloz.colorrecipesexplorer.config.defaultGroupCookieName
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.model.validation.or
import dev.fyloz.colorrecipesexplorer.repository.EmployeeGroupRepository
import dev.fyloz.colorrecipesexplorer.repository.EmployeeRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Lazy
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
@ -74,8 +75,10 @@ interface EmployeeUserDetailsService : UserDetailsService {
}
@Service
class EmployeeServiceImpl(employeeRepository: EmployeeRepository, val passwordEncoder: PasswordEncoder) :
AbstractExternalModelService<Employee, EmployeeSaveDto, EmployeeUpdateDto, EmployeeRepository>(employeeRepository),
class EmployeeServiceImpl(
employeeRepository: EmployeeRepository,
@Lazy val passwordEncoder: PasswordEncoder
) : AbstractExternalModelService<Employee, EmployeeSaveDto, EmployeeUpdateDto, EmployeeRepository>(employeeRepository),
EmployeeService {
@Autowired
lateinit var groupService: EmployeeGroupServiceImpl

View File

@ -1,11 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
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.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.colorrecipesexplorer.model.Company
import dev.fyloz.colorrecipesexplorer.model.CompanySaveDto
import dev.fyloz.colorrecipesexplorer.model.CompanyUpdateDto
import dev.fyloz.colorrecipesexplorer.model.company
import dev.fyloz.colorrecipesexplorer.repository.CompanyRepository
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service

View File

@ -1,12 +1,12 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.exception.LowQuantitiesException
import dev.fyloz.trial.colorrecipesexplorer.exception.LowQuantityException
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialQuantityDto
import dev.fyloz.trial.colorrecipesexplorer.model.MixDeductDto
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial
import dev.fyloz.trial.colorrecipesexplorer.model.materialQuantityDto
import dev.fyloz.trial.colorrecipesexplorer.service.utils.mapMayThrow
import dev.fyloz.colorrecipesexplorer.exception.LowQuantitiesException
import dev.fyloz.colorrecipesexplorer.exception.LowQuantityException
import dev.fyloz.colorrecipesexplorer.model.MaterialQuantityDto
import dev.fyloz.colorrecipesexplorer.model.MixDeductDto
import dev.fyloz.colorrecipesexplorer.model.MixMaterial
import dev.fyloz.colorrecipesexplorer.model.materialQuantityDto
import dev.fyloz.colorrecipesexplorer.service.utils.mapMayThrow
import org.springframework.stereotype.Service
import javax.transaction.Transactional

View File

@ -1,10 +1,11 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
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
import dev.fyloz.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MaterialRepository
import dev.fyloz.colorrecipesexplorer.service.files.SimdutService
import io.jsonwebtoken.lang.Assert
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
interface MaterialService :
@ -39,9 +40,12 @@ class MaterialServiceImpl(
materialRepository: MaterialRepository,
val simdutService: SimdutService,
val recipeService: RecipeService,
val mixService: MixService
val mixService: MixService,
@Lazy val materialTypeService: MaterialTypeService
) :
AbstractExternalNamedModelService<Material, MaterialSaveDto, MaterialUpdateDto, MaterialRepository>(materialRepository),
AbstractExternalNamedModelService<Material, MaterialSaveDto, MaterialUpdateDto, MaterialRepository>(
materialRepository
),
MaterialService {
override fun existsByMaterialType(materialType: MaterialType): Boolean =
repository.existsByMaterialType(materialType)
@ -56,7 +60,14 @@ class MaterialServiceImpl(
.map { it.id!! }
override fun save(entity: MaterialSaveDto): Material =
save(entity.toMaterial()).apply {
save(with(entity) {
material(
name = entity.name,
inventoryQuantity = entity.inventoryQuantity,
materialType = materialTypeService.getById(materialTypeId),
isMixType = false
)
}).apply {
if (entity.simdutFile != null && !entity.simdutFile.isEmpty) simdutService.write(this, entity.simdutFile)
}
@ -64,7 +75,6 @@ class MaterialServiceImpl(
val persistedMaterial by lazy {
getById(entity.id).apply { assertPersistedMaterial(this) }
}
assertMaterialType(entity.materialType)
return update(with(entity) {
material(
@ -72,7 +82,7 @@ class MaterialServiceImpl(
name = if (name != null && name.isNotBlank()) name else persistedMaterial.name,
inventoryQuantity = if (inventoryQuantity != null && inventoryQuantity != Float.MIN_VALUE) inventoryQuantity else persistedMaterial.inventoryQuantity,
isMixType = persistedMaterial.isMixType,
materialType = materialType ?: persistedMaterial.materialType!!
materialType = if (materialTypeId != null) materialTypeService.getById(materialTypeId) else persistedMaterial.materialType
)
}).apply {
if (entity.simdutFile != null && !entity.simdutFile.isEmpty) simdutService.update(entity.simdutFile, this)
@ -99,10 +109,6 @@ class MaterialServiceImpl(
.filter { it.id != mix.mixType.material.id }
}
private fun assertMaterialType(materialType: MaterialType?) {
Assert.notNull(materialType, "A persisted material has a null material type")
}
private fun assertPersistedMaterial(material: Material) {
Assert.notNull(material.name, "The persisted material with the id ${material.id} has a null name")
}

View File

@ -1,15 +1,15 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.trial.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.trial.colorrecipesexplorer.exception.RestException
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
import dev.fyloz.trial.colorrecipesexplorer.model.materialType
import dev.fyloz.trial.colorrecipesexplorer.model.validation.isNotNullAndNotBlank
import dev.fyloz.trial.colorrecipesexplorer.repository.MaterialTypeRepository
import dev.fyloz.colorrecipesexplorer.config.properties.MaterialTypeProperties
import dev.fyloz.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.colorrecipesexplorer.exception.RestException
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.MaterialTypeSaveDto
import dev.fyloz.colorrecipesexplorer.model.MaterialTypeUpdateDto
import dev.fyloz.colorrecipesexplorer.model.materialType
import dev.fyloz.colorrecipesexplorer.model.validation.isNotNullAndNotBlank
import dev.fyloz.colorrecipesexplorer.repository.MaterialTypeRepository
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.web.bind.annotation.ResponseStatus

View File

@ -0,0 +1,45 @@
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.model.MixMaterial
import dev.fyloz.colorrecipesexplorer.model.MixMaterialDto
import dev.fyloz.colorrecipesexplorer.model.mixMaterial
import dev.fyloz.colorrecipesexplorer.repository.MixMaterialRepository
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
interface MixMaterialService : ModelService<MixMaterial, MixMaterialRepository> {
/** Checks if one or more mix materials have the given [material]. */
fun existsByMaterial(material: Material): Boolean
/** Creates [MixMaterial]s from the givens [MixMaterialDto]. */
fun create(mixMaterials: Set<MixMaterialDto>): Set<MixMaterial>
/** Creates a [MixMaterial] from a given [MixMaterialDto]. */
fun create(mixMaterial: MixMaterialDto): MixMaterial
/** Updates the [quantity] of the given [mixMaterial]. */
fun updateQuantity(mixMaterial: MixMaterial, quantity: Float): MixMaterial
}
@Service
class MixMaterialServiceImpl(
mixMaterialRepository: MixMaterialRepository,
@Lazy val materialService: MaterialService
) : AbstractModelService<MixMaterial, MixMaterialRepository>(mixMaterialRepository), MixMaterialService {
override fun existsByMaterial(material: Material): Boolean = repository.existsByMaterial(material)
override fun create(mixMaterials: Set<MixMaterialDto>): Set<MixMaterial> =
mixMaterials.map(::create).toSet()
override fun create(mixMaterial: MixMaterialDto): MixMaterial =
mixMaterial(
material = materialService.getById(mixMaterial.materialId),
quantity = mixMaterial.quantity,
position = mixMaterial.position
)
override fun updateQuantity(mixMaterial: MixMaterial, quantity: Float) =
update(mixMaterial.apply {
this.quantity = quantity
})
}

View File

@ -0,0 +1,92 @@
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixRepository
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
import javax.transaction.Transactional
interface MixService : ExternalModelService<Mix, MixSaveDto, MixUpdateDto, MixRepository> {
/** Gets all mixes with the given [mixType]. */
fun getAllByMixType(mixType: MixType): Collection<Mix>
/** Checks if a [MixType] is shared by several [Mix]es or not. */
fun mixTypeIsShared(mixType: MixType): Boolean
/** Updates the location of each [Mix] in the given [MixLocationDto]s. */
fun updateLocations(updatedLocations: Collection<MixLocationDto>)
/** Updates the location of a given [Mix] to the given [MixLocationDto]. */
fun updateLocation(updatedLocation: MixLocationDto)
}
@Service
class MixServiceImpl(
mixRepository: MixRepository,
@Lazy val recipeService: RecipeService,
@Lazy val materialTypeService: MaterialTypeService,
val mixMaterialService: MixMaterialService,
val mixTypeService: MixTypeService
) : AbstractModelService<Mix, MixRepository>(mixRepository),
MixService {
override fun getAllByMixType(mixType: MixType): Collection<Mix> = repository.findAllByMixType(mixType)
override fun mixTypeIsShared(mixType: MixType): Boolean = getAllByMixType(mixType).count() > 1
@Transactional
override fun save(entity: MixSaveDto): Mix {
val recipe = recipeService.getById(entity.recipeId)
val materialType = materialTypeService.getById(entity.materialTypeId)
val mixType = mixTypeService.getOrCreateForNameAndMaterialType(entity.name, materialType)
val mixMaterials = if (entity.mixMaterials != null) mixMaterialService.create(entity.mixMaterials) else setOf()
var mix = mix(recipe = recipe, mixType = mixType, mixMaterials = mixMaterials.toMutableSet())
mix = save(mix)
recipeService.addMix(recipe, mix)
return mix
}
@Transactional
override fun update(entity: MixUpdateDto): Mix {
val mix = getById(entity.id)
if (entity.name != null || entity.materialTypeId != null) {
val name = entity.name ?: mix.mixType.name
val materialType = if (entity.materialTypeId != null)
materialTypeService.getById(entity.materialTypeId)
else
mix.mixType.material.materialType!!
mix.mixType = if (mixTypeIsShared(mix.mixType)) {
mixTypeService.saveForNameAndMaterialType(name, materialType)
} else {
mixTypeService.updateForNameAndMaterialType(mix.mixType, name, materialType)
}
}
if (entity.mixMaterials != null) {
mix.mixMaterials.clear()
mix.mixMaterials.addAll(mixMaterialService.create(entity.mixMaterials!!).toMutableSet())
}
return update(mix)
}
override fun updateLocations(updatedLocations: Collection<MixLocationDto>) {
updatedLocations.forEach(::updateLocation)
}
override fun updateLocation(updatedLocation: MixLocationDto) {
repository.updateLocationById(updatedLocation.mixId, updatedLocation.location)
}
@Transactional
override fun delete(entity: Mix) {
recipeService.removeMix(entity)
super.delete(entity)
}
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}
}

View File

@ -1,10 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
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 dev.fyloz.colorrecipesexplorer.exception.CannotDeleteEntityException
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixTypeRepository
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service

View File

@ -1,16 +1,16 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
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.FileService
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.model.validation.or
import dev.fyloz.colorrecipesexplorer.repository.RecipeRepository
import dev.fyloz.colorrecipesexplorer.service.files.FileService
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.nio.file.NoSuchFileException
import kotlin.contracts.ExperimentalContracts
import javax.transaction.Transactional
interface RecipeService : ExternalModelService<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeRepository> {
/** Checks if one or more recipes have the given [company]. */
@ -34,7 +34,7 @@ class RecipeServiceImpl(
recipeRepository: RecipeRepository,
val companyService: CompanyService,
val mixService: MixService,
val stepService: RecipeStepService
@Lazy val groupService: EmployeeGroupService
) :
AbstractExternalModelService<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeRepository>(recipeRepository),
RecipeService {
@ -57,7 +57,7 @@ class RecipeServiceImpl(
})
}
@ExperimentalContracts
@Transactional
override fun update(entity: RecipeUpdateDto): Recipe {
val persistedRecipe by lazy { getById(entity.id) }
@ -71,44 +71,58 @@ class RecipeServiceImpl(
sample = sample ?: persistedRecipe.sample,
approbationDate = approbationDate ?: persistedRecipe.approbationDate,
remark = remark or persistedRecipe.remark,
note = persistedRecipe.note,
company = persistedRecipe.company,
mixes = persistedRecipe.mixes,
steps = updateSteps(persistedRecipe, steps)
groupsInformation = updateGroupsInformationSteps(persistedRecipe, entity.steps)
)
})
}
private fun updateSteps(recipe: Recipe, steps: List<RecipeStep>?): List<RecipeStep> =
if (steps != null) {
val toDelete = recipe.steps.filter { !steps.any { step -> step.message == it.message } }
toDelete.forEach(stepService::delete)
recipe.steps
.filter { !toDelete.any { step -> step.message == it.message } } + steps
.map { recipeStep(recipe = recipe, message = it.message) }
.filter { !recipe.steps.any { step -> step.message == it.message } }
.toMutableList()
} else {
recipe.steps
}
private fun updateGroupsInformationSteps(recipe: Recipe, steps: Set<RecipeStepsDto>?): Set<RecipeGroupInformation> {
if (steps == null) return recipe.groupsInformation
@ExperimentalContracts
override fun updatePublicData(publicDataDto: RecipePublicDataDto) {
val recipe = getById(publicDataDto.id)
if (isNotNullAndNotBlank(publicDataDto.note)) {
update(recipe.apply { note = publicDataDto.note })
}
with(publicDataDto.mixesLocation) {
if (!isNullOrEmpty()) {
// Map each mix ID to their mix in the recipe
map { recipe.mixes.firstOrNull { mix -> mix.id == it.key } to it.value }
// Remove pairs with a null mix
.filter { it.first != null }
.forEach { mixService.updateLocation(it.first!!, it.second) }
val updatedGroupsInformation = mutableSetOf<RecipeGroupInformation>()
steps.forEach {
with(recipe.groupInformationForGroup(it.groupId)) {
updatedGroupsInformation.add(
this?.apply {
if (this.steps != null) {
this.steps!!.clear()
this.steps!!.addAll(it.steps)
} else {
this.steps = it.steps.toMutableSet()
}
} ?: recipeGroupInformation(
group = groupService.getById(it.groupId),
steps = it.steps.toMutableSet()
)
)
}
}
return updatedGroupsInformation
}
override fun updatePublicData(publicDataDto: RecipePublicDataDto) {
if (publicDataDto.notes != null) {
val recipe = getById(publicDataDto.recipeId)
fun noteForGroup(group: EmployeeGroup) =
publicDataDto.notes.firstOrNull { it.groupId == group.id }?.content
// Notes
recipe.groupsInformation.map {
val updatedNote = noteForGroup(it.group)
it.apply {
note = updatedNote
}
}
update(recipe)
}
if (publicDataDto.mixesLocation != null) {
mixService.updateLocations(publicDataDto.mixesLocation)
}
}
override fun addMix(recipe: Recipe, mix: Mix) =

View File

@ -0,0 +1,12 @@
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.colorrecipesexplorer.model.RecipeStep
import dev.fyloz.colorrecipesexplorer.repository.RecipeStepRepository
import org.springframework.stereotype.Service
interface RecipeStepService : ModelService<RecipeStep, RecipeStepRepository>
@Service
class RecipeStepServiceImpl(recipeStepRepository: RecipeStepRepository) :
AbstractModelService<RecipeStep, RecipeStepRepository>(recipeStepRepository),
RecipeStepService

View File

@ -1,13 +1,13 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
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
import dev.fyloz.trial.colorrecipesexplorer.repository.NamedJpaRepository
import dev.fyloz.trial.colorrecipesexplorer.rest.RestApiController
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.EntityDto
import dev.fyloz.colorrecipesexplorer.model.Model
import dev.fyloz.colorrecipesexplorer.model.NamedModel
import dev.fyloz.colorrecipesexplorer.repository.NamedJpaRepository
import dev.fyloz.colorrecipesexplorer.rest.RestApiController
import io.jsonwebtoken.lang.Assert
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.repository.findByIdOrNull

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files
package dev.fyloz.colorrecipesexplorer.service.files
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CreProperties
import dev.fyloz.colorrecipesexplorer.config.properties.CreProperties
import org.slf4j.Logger
import org.springframework.core.io.ResourceLoader
import org.springframework.stereotype.Service

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.service.files
package dev.fyloz.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 dev.fyloz.colorrecipesexplorer.exception.SimdutWriteException
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.service.MaterialService
import org.slf4j.Logger
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service

View File

@ -1,4 +1,4 @@
package dev.fyloz.trial.colorrecipesexplorer.service.utils
package dev.fyloz.colorrecipesexplorer.service.utils
/** Returns a list containing the result of the given [transform] applied to each item of the [Iterable]. If the given [transform] throws, the [Throwable] will be passed to the given [throwableConsumer]. */
inline fun <T, R, reified E : Throwable> Iterable<T>.mapMayThrow(

View File

@ -1,58 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model
import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank
import java.util.*
import javax.persistence.*
import javax.validation.constraints.NotBlank
import javax.validation.constraints.NotNull
private const val COMPANY_ID_NULL_MESSAGE = "Un identifiant est requis"
private const val COMPANY_NAME_NULL_MESSAGE = "Un nom est requis"
@Entity
@Table(name = "company")
data class Company(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@Column(unique = true)
override val name: String
) : NamedModel
open class CompanySaveDto(
@field:NotBlank(message = COMPANY_NAME_NULL_MESSAGE)
val name: String
) : EntityDto<Company> {
override fun toEntity(): Company = Company(null, name)
}
open class CompanyUpdateDto(
@field:NotNull(message = COMPANY_ID_NULL_MESSAGE)
val id: Long,
@field:NullOrNotBlank(message = COMPANY_NAME_NULL_MESSAGE)
val name: String?
) : EntityDto<Company> {
override fun toEntity(): Company = Company(id, name ?: "")
}
// ==== DSL ====
fun company(
id: Long? = null,
name: String = "name",
op: Company.() -> Unit = {}
) = Company(id, name).apply(op)
fun companySaveDto(
name: String = "name",
op: CompanySaveDto.() -> Unit = {}
) = CompanySaveDto(name).apply(op)
fun companyUpdateDto(
id: Long = 0L,
name: String? = "name",
op: CompanyUpdateDto.() -> Unit = {}
) = CompanyUpdateDto(id, name).apply(op)

View File

@ -1,34 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.model
import com.fasterxml.jackson.annotation.JsonIgnore
import java.util.*
import javax.persistence.*
@Entity
@Table(name = "mix_material")
data class MixMaterial(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@JsonIgnore
@ManyToOne
@JoinColumn(name = "mix_id")
val mix: Mix,
@ManyToOne
@JoinColumn(name = "material_id")
val material: Material,
var quantity: Float
) : Model
// ==== DSL ====
fun mixMaterial(
id: Long? = null,
mix: Mix = mix(),
material: Material = material(),
quantity: Float = 0f,
op: MixMaterial.() -> Unit = {}
) = MixMaterial(id, mix, material, quantity).apply(op)

View File

@ -1,16 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.rest
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeSaveDto
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeUpdateDto
import dev.fyloz.trial.colorrecipesexplorer.service.MaterialTypeService
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
private const val MATERIAL_TYPE_CONTROLLER_PATH = "api/materialtype"
@RestController
@RequestMapping(MATERIAL_TYPE_CONTROLLER_PATH)
class MaterialTypeController(materialTypeService: MaterialTypeService) :
AbstractModelRestApiController<MaterialType, MaterialTypeSaveDto, MaterialTypeUpdateDto, MaterialTypeService>(materialTypeService, MATERIAL_TYPE_CONTROLLER_PATH)

View File

@ -1,41 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial
import dev.fyloz.trial.colorrecipesexplorer.model.mixMaterial
import dev.fyloz.trial.colorrecipesexplorer.repository.MixMaterialRepository
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
interface MixMaterialService : ModelService<MixMaterial, MixMaterialRepository> {
/** Checks if one or more mix materials have the given [material]. */
fun existsByMaterial(material: Material): Boolean
/** Creates [MixMaterial]s from the given [map]. The [map] must have the format <Material ID, Quantity>. */
fun createFromMap(mix: Mix, map: Map<Long, Float>): Collection<MixMaterial>
/** Creates a [MixMaterial] with the material with the given [materialId] and the given [quantity]. */
fun create(mix: Mix, materialId: Long, quantity: Float): MixMaterial
/** Updates the [quantity] of the given [mixMaterial]. */
fun updateQuantity(mixMaterial: MixMaterial, quantity: Float): MixMaterial
}
@Service
class MixMaterialServiceImpl(
mixMaterialRepository: MixMaterialRepository,
@Lazy val materialService: MaterialService
) : AbstractModelService<MixMaterial, MixMaterialRepository>(mixMaterialRepository), MixMaterialService {
override fun existsByMaterial(material: Material): Boolean = repository.existsByMaterial(material)
override fun createFromMap(mix: Mix, map: Map<Long, Float>): Collection<MixMaterial> =
map.map { create(mix, it.key, it.value) }
override fun create(mix: Mix, materialId: Long, quantity: Float): MixMaterial =
mixMaterial(mix = mix, material = materialService.getById(materialId), quantity = quantity)
override fun updateQuantity(mixMaterial: MixMaterial, quantity: Float) =
update(mixMaterial.apply {
this.quantity = quantity
})
}

View File

@ -1,120 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service
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
import org.springframework.stereotype.Service
import javax.transaction.Transactional
interface MixService : ExternalModelService<Mix, MixSaveDto, MixUpdateDto, MixRepository> {
/** Gets all mixes with the given [mixType]. */
fun getAllByMixType(mixType: MixType): Collection<Mix>
/** Checks if a [MixType] is shared by several [Mix]es or not. */
fun mixTypeIsShared(mixType: MixType): Boolean
/** Updates the location of the given [mix] to the given [location]. */
fun updateLocation(mix: Mix, location: String)
}
@Service
class MixServiceImpl(
mixRepository: MixRepository,
@Lazy val recipeService: RecipeService,
@Lazy val materialTypeService: MaterialTypeService,
val mixMaterialService: MixMaterialService,
val mixTypeService: MixTypeService
) : AbstractModelService<Mix, MixRepository>(mixRepository),
MixService {
override fun getAllByMixType(mixType: MixType): Collection<Mix> = repository.findAllByMixType(mixType)
override fun mixTypeIsShared(mixType: MixType): Boolean = getAllByMixType(mixType).count() > 1
@Transactional
override fun save(entity: MixSaveDto): Mix {
val recipe = recipeService.getById(entity.recipeId)
val materialType = materialTypeService.getById(entity.materialTypeId)
val mixType = mixTypeService.getOrCreateForNameAndMaterialType(entity.name, materialType)
var mix = mix(recipe = recipe, mixType = mixType)
mix = save(mix)
val mixMaterials =
if (entity.mixMaterials != null) mixMaterialService.createFromMap(mix, entity.mixMaterials) else listOf()
mix = update(
mix(
id = mix.id,
location = null,
recipe = recipe,
mixType = mixType,
mixMaterials = mixMaterials.toMutableList()
)
)
recipeService.addMix(recipe, mix)
return mix
}
@Transactional
override fun update(entity: MixUpdateDto): Mix {
fun updateMixMaterials(mix: Mix, mixMaterialsMap: Map<Long, Float>) {
val existingMixMaterialsMaterialIds = mix.mixMaterials.map { it.material.id }
val toDelete = mix.mixMaterials
mix.mixMaterials = mutableListOf(
// update existing mix materials
*mixMaterialsMap
.filter { it.key in existingMixMaterialsMaterialIds }
.map { (materialId, quantity) ->
val existingMixMaterial = mix.mixMaterials.first { it.material.id == materialId }
toDelete.remove(existingMixMaterial)
mixMaterialService.updateQuantity(existingMixMaterial, quantity)
}
.toTypedArray(),
// create new mix materials
*mixMaterialsMap
.filter { it.key !in existingMixMaterialsMaterialIds }
.map { (materialId, quantity) -> mixMaterialService.create(mix, materialId, quantity) }
.toTypedArray()
)
// delete unused mix materials
toDelete.forEach { mixMaterialService.delete(it) }
}
val mix = getById(entity.id)
if (entity.name != null || entity.materialTypeId != null) {
mix.mixType = if (mixTypeIsShared(mix.mixType)) {
mixTypeService.saveForNameAndMaterialType(
entity.name ?: mix.mixType.name,
if (entity.materialTypeId != null) materialTypeService.getById(entity.materialTypeId) else mix.mixType.material.materialType!!
)
} else {
mixTypeService.updateForNameAndMaterialType(
mix.mixType,
entity.name ?: mix.mixType.name,
if (entity.materialTypeId != null) materialTypeService.getById(entity.materialTypeId) else mix.mixType.material.materialType!!
)
}
}
if (entity.mixMaterials != null) {
updateMixMaterials(mix, entity.mixMaterials)
}
return update(mix)
}
override fun updateLocation(mix: Mix, location: String) {
update(mix.apply { this.location = location })
}
@Transactional
override fun delete(entity: Mix) {
recipeService.removeMix(entity)
super.delete(entity)
}
override fun deleteById(id: Long) {
if (!repository.canBeDeleted(id)) throw CannotDeleteEntityException(id)
super.deleteById(id)
}
}

View File

@ -1,28 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeStep
import dev.fyloz.trial.colorrecipesexplorer.model.recipeStep
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeStepRepository
import org.springframework.stereotype.Service
import javax.transaction.Transactional
interface RecipeStepService : ModelService<RecipeStep, RecipeStepRepository> {
/** Creates a step for the given [recipe] with the given [message]. */
fun createForRecipe(recipe: Recipe, message: String): RecipeStep
/** Creates several steps for the given [recipe] with the given [messages]. */
fun createAllForRecipe(recipe: Recipe, messages: Collection<String>): Collection<RecipeStep>
}
@Service
class RecipeStepServiceImpl(recipeStepRepository: RecipeStepRepository) :
AbstractModelService<RecipeStep, RecipeStepRepository>(recipeStepRepository),
RecipeStepService {
override fun createForRecipe(recipe: Recipe, message: String): RecipeStep =
recipeStep(recipe = recipe, message = message)
@Transactional
override fun createAllForRecipe(recipe: Recipe, messages: Collection<String>): Collection<RecipeStep> =
messages.map { createForRecipe(recipe, it) }
}

View File

@ -1,6 +1,6 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.material
import dev.fyloz.colorrecipesexplorer.model.material
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration

View File

@ -0,0 +1,41 @@
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.colorrecipesexplorer.model.*
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager
import kotlin.test.assertEquals
@DataJpaTest(excludeAutoConfiguration = [LiquibaseAutoConfiguration::class])
class MixRepositoryTest @Autowired constructor(
private val mixRepository: MixRepository,
private val entityManager: TestEntityManager
) {
// updateLocationById()
@Test
fun `updateLocationById() updates the location of the mix with the given identifier`() {
withMixLocation(null) { mix ->
val updatedLocation = "new location"
mixRepository.updateLocationById(mix.id!!, updatedLocation)
val updated = entityManager.refresh(mix)
assertEquals(updatedLocation, updated.location)
}
}
private fun withMixLocation(location: String?, test: (Mix) -> Unit) {
val materialType = entityManager.persist(materialType())
val mixType = entityManager.persist(mixType(materialType = materialType))
val company = entityManager.persist(company())
val recipe = entityManager.persist(recipe(company = company))
val mix = mix(id = null, location = location, recipe = recipe, mixType = mixType)
test(entityManager.persist(mix))
}
}

View File

@ -1,12 +1,12 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
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
import dev.fyloz.trial.colorrecipesexplorer.repository.NamedJpaRepository
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.EntityDto
import dev.fyloz.colorrecipesexplorer.model.Model
import dev.fyloz.colorrecipesexplorer.model.NamedModel
import dev.fyloz.colorrecipesexplorer.repository.NamedJpaRepository
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
@ -15,7 +15,7 @@ import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractServiceTest as AbstractServiceTest1
import dev.fyloz.colorrecipesexplorer.service.AbstractServiceTest as AbstractServiceTest1
abstract class AbstractServiceTest<E, S : Service<E, *>, R : JpaRepository<E, *>> {
protected abstract val repository: R

View File

@ -1,12 +1,12 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.config.defaultGroupCookieName
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.EmployeeGroupRepository
import dev.fyloz.trial.colorrecipesexplorer.repository.EmployeeRepository
import dev.fyloz.colorrecipesexplorer.config.defaultGroupCookieName
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.EmployeeGroupRepository
import dev.fyloz.colorrecipesexplorer.repository.EmployeeRepository
import org.junit.jupiter.api.*
import org.junit.jupiter.api.Test
import org.springframework.mock.web.MockHttpServletResponse

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.CompanyRepository
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.CompanyRepository
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import kotlin.test.assertFalse

View File

@ -1,9 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.exception.LowQuantitiesException
import dev.fyloz.trial.colorrecipesexplorer.exception.LowQuantityException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.exception.LowQuantitiesException
import dev.fyloz.colorrecipesexplorer.exception.LowQuantityException
import dev.fyloz.colorrecipesexplorer.model.*
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
@ -68,9 +68,9 @@ class InventoryServiceTest {
val mixRatio = mixRatio(ratio = 1.5f)
val mix = mix(
id = mixRatio.id,
mixMaterials = mutableListOf(
mixMaterial(id = 0L, material = material, quantity = 1000f),
mixMaterial(id = 1L, material = materialPercents, quantity = 50f)
mixMaterials = mutableSetOf(
mixMaterial(id = 0L, material = material, quantity = 1000f, position = 0),
mixMaterial(id = 1L, material = materialPercents, quantity = 50f, position = 1)
)
)
val expectedQuantities = mapOf(

View File

@ -1,10 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MaterialRepository
import dev.fyloz.trial.colorrecipesexplorer.service.files.SimdutService
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MaterialRepository
import dev.fyloz.colorrecipesexplorer.service.files.SimdutService
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
@ -19,8 +19,9 @@ class MaterialServiceTest :
private val simdutService: SimdutService = mock()
private val recipeService: RecipeService = mock()
private val mixService: MixService = mock()
private val materialTypeService: MaterialTypeService = mock()
override val service: MaterialService =
spy(MaterialServiceImpl(repository, simdutService, recipeService, mixService))
spy(MaterialServiceImpl(repository, simdutService, recipeService, mixService, materialTypeService))
override val entity: Material = material(id = 0L, name = "material")
override val anotherEntity: Material = material(id = 1L, name = "another material")
@ -132,7 +133,7 @@ class MaterialServiceTest :
@Test
override fun `save(dto) calls and returns save() with the created entity`() {
withBaseSaveDtoTest(entity, entitySaveDto, service)
withBaseSaveDtoTest(entity, entitySaveDto, service, { any() })
}
@Test
@ -141,8 +142,7 @@ class MaterialServiceTest :
val materialSaveDto = spy(materialSaveDto(simdutFile = mockMultipartFile))
doReturn(false).whenever(mockMultipartFile).isEmpty
doReturn(entity).whenever(materialSaveDto).toEntity()
doReturn(entity).whenever(service).save(entity)
doReturn(entity).whenever(service).save(any<Material>())
service.save(materialSaveDto)

View File

@ -1,10 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
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.MaterialTypeRepository
import dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MaterialTypeRepository
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows

View File

@ -1,8 +1,8 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MixMaterialRepository
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixMaterialRepository
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
@ -38,40 +38,52 @@ class MixMaterialServiceTest : AbstractModelServiceTest<MixMaterial, MixMaterial
assertFalse(found)
}
// createFromMap()
@Test
fun `createFromMap() calls create() for each map entry`() {
val mix = mix()
val map = mapOf(
1L to 1000f,
2L to 2000f,
5L to 5000f
)
val mixMaterials = map.map { mixMaterial(material = material(id = it.key), quantity = it.value) }
doAnswer { mixMaterials.first { mixMaterial -> mixMaterial.material.id == it.arguments[1] } }
.whenever(service).create(eq(mix), any(), any())
val found = service.createFromMap(mix, map)
assertEquals(mixMaterials, found)
}
// create()
@Test
fun `create() creates a mix material with the given mix, material and quantity`() {
val mix = mix()
val material = material(id = 0L)
val quantity = 1000f
val mixMaterial = mixMaterial(mix = mix, material = material, quantity = quantity)
fun `create(set) calls create() for each MixMaterialDto`() {
val mixMaterialDtos = setOf(
mixMaterialDto(materialId = 0L, quantity = 1000f, position = 1),
mixMaterialDto(materialId = 1L, quantity = 2000f, position = 2),
mixMaterialDto(materialId = 2L, quantity = 3000f, position = 3),
mixMaterialDto(materialId = 3L, quantity = 4000f, position = 4)
)
whenever(materialService.getById(material.id!!)).doReturn(material)
doAnswer {
with(it.arguments[0] as MixMaterialDto) {
mixMaterial(
material = material(id = this.materialId),
quantity = this.quantity,
position = this.position
)
}
}.whenever(service).create(any<MixMaterialDto>())
val found = service.create(mix, material.id!!, quantity)
val found = service.create(mixMaterialDtos)
assertEquals(mixMaterial, found)
mixMaterialDtos.forEach { dto ->
verify(service).create(dto)
assertTrue {
found.any {
it.material.id == dto.materialId && it.quantity == dto.quantity && it.position == dto.position
}
}
}
}
@Test
fun `create() creates a mix material according to the given MixUpdateDto`() {
val mixMaterialDto = mixMaterialDto(materialId = 0L, quantity = 1000f, position = 1)
whenever(materialService.getById(mixMaterialDto.materialId)).doAnswer { material(id = it.arguments[0] as Long) }
val found = service.create(mixMaterialDto)
assertTrue {
found.material.id == mixMaterialDto.materialId &&
found.quantity == mixMaterialDto.quantity &&
found.position == mixMaterialDto.position
}
}
// updateQuantity()

View File

@ -1,8 +1,9 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixRepository
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@ -18,9 +19,16 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
override val entity: Mix = mix(id = 0L, location = "location")
override val anotherEntity: Mix = mix(id = 1L)
override val entitySaveDto: MixSaveDto = spy(mixSaveDto(mixMaterials = mapOf(1L to 1000f)))
override val entitySaveDto: MixSaveDto =
spy(mixSaveDto(mixMaterials = setOf(mixMaterialDto(materialId = 1L, quantity = 1000f, position = 0))))
override val entityUpdateDto: MixUpdateDto = spy(mixUpdateDto(id = entity.id!!))
@AfterEach
override fun afterEach() {
super.afterEach()
reset(recipeService, materialTypeService, mixMaterialService, mixTypeService)
}
// getAllByMixType()
@Test
@ -49,11 +57,11 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
val mixType = mixType(name = entitySaveDto.name, material = material)
val mix = mix(recipe = recipe, mixType = mixType)
val mixWithId = mix(id = 0L, recipe = recipe, mixType = mixType)
val mixMaterials = listOf(mixMaterial(mix = mixWithId, material = material(id = 1L), quantity = 1000f))
val mixMaterials = setOf(mixMaterial(material = material(id = 1L), quantity = 1000f))
whenever(recipeService.getById(recipe.id!!)).doReturn(recipe)
whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType)
whenever(mixMaterialService.createFromMap(mixWithId, entitySaveDto.mixMaterials!!)).doReturn(mixMaterials)
whenever(mixMaterialService.create(entitySaveDto.mixMaterials!!)).doReturn(mixMaterials)
whenever(
mixTypeService.getOrCreateForNameAndMaterialType(
mixType.name,
@ -62,12 +70,10 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
).doReturn(mixType)
doReturn(true).whenever(service).existsById(mixWithId.id!!)
doReturn(mixWithId).whenever(service).save(any<Mix>())
doReturn(mixWithId).whenever(service).update(any<Mix>())
val found = service.save(entitySaveDto)
verify(service).save(argThat<Mix> { this.recipe == mix.recipe })
verify(service).update(argThat<Mix> { this.id == mixWithId.id && this.recipe == mixWithId.recipe && this.mixMaterials == mixMaterials })
verify(recipeService).addMix(recipe, mixWithId)
// Verify if this method is called instead of the MixType's constructor, which does not check if the name is already taken by a material.
@ -148,56 +154,70 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
@Test
fun `update(dto) update, create and delete mix materials according to the given mix materials map`() {
mixUpdateDtoTest {
// Pairs exists, impairs don't
val materials = listOf(
material(id = 1L),
material(id = 2L),
material(id = 3L),
material(id = 4L),
material(id = 5L),
material(id = 6L),
val mixMaterials = setOf(
mixMaterialDto(materialId = 0L, quantity = 100f, position = 0),
mixMaterialDto(materialId = 1L, quantity = 200f, position = 1),
mixMaterialDto(materialId = 2L, quantity = 300f, position = 2),
mixMaterialDto(materialId = 3L, quantity = 400f, position = 3),
)
val toDelete = mixMaterial(material = material(id = 7L), quantity = 7000f)
val mixMaterialsMap = mapOf(*materials.map { it.id!! to it.id!! * 1000f }.toTypedArray())
val allMixMaterials: Collection<MixMaterial> = materials
.map { mixMaterial(mix = mix, material = it, quantity = mixMaterialsMap[it.id]!!) }
val existingMixMaterials = allMixMaterials.filter { it.material.id!! % 2 == 0L }.toMutableList()
existingMixMaterials += toDelete
mixUpdateDto.mixMaterials = mixMaterials
mix.mixMaterials = existingMixMaterials
(mixUpdateDto.mixMaterials as MutableMap<Long, Float>).putAll(mixMaterialsMap)
whenever(mixMaterialService.create(any<Set<MixMaterialDto>>())).doAnswer {
(it.arguments[0] as Set<MixMaterialDto>).map { dto ->
mixMaterial(
material = material(id = dto.materialId),
quantity = dto.quantity,
position = dto.position
)
}.toSet()
}
doAnswer { allMixMaterials.first { mixMaterial -> mixMaterial.material.id == (it.arguments[0] as MixMaterial).material.id } }
.whenever(mixMaterialService).updateQuantity(any(), any())
doAnswer { allMixMaterials.first { mixMaterial -> mixMaterial.material.id == it.arguments[1] } }
.whenever(mixMaterialService).create(eq(mix), any(), any())
val found = service.update(mixUpdateDto)
val found: Mix = service.update(mixUpdateDto)
mixMaterials.forEach {
assertTrue {
found.mixMaterials.any { mixMaterial ->
mixMaterial.material.id == it.materialId && mixMaterial.quantity == it.quantity && mixMaterial.position == it.position
}
}
}
}
}
assertTrue { found.mixMaterials.containsAll(allMixMaterials) }
// updateLocations()
verify(mixMaterialService, times(3)).updateQuantity(argThat { material.id!! % 2 == 0L }, any())
verify(mixMaterialService, times(3)).create(eq(mix), any(), any())
verify(mixMaterialService).delete(toDelete)
@Test
fun `updateLocations() calls updateLocation() for each given MixLocationDto`() {
val locations = setOf(
mixLocationDto(mixId = 0, location = "Loc 0"),
mixLocationDto(mixId = 1, location = "Loc 1"),
mixLocationDto(mixId = 2, location = "Loc 2"),
mixLocationDto(mixId = 3, location = "Loc 3")
)
service.updateLocations(locations)
locations.forEach {
verify(service).updateLocation(it)
}
}
// updateLocation()
@Test
fun `updateLocation() calls update() with the given mix with the given location`() {
val newLocation = "new location"
val expected = entity.apply { location = newLocation }
doReturn(expected).whenever(service).update(expected)
fun `updateLocation() updates the location of a mix in the repository according to the given MixLocationDto`() {
val locationDto = mixLocationDto(mixId = 0L, location = "Location")
service.updateLocation(entity, newLocation)
service.updateLocation(locationDto)
verify(service).update(expected)
verify(repository).updateLocationById(locationDto.mixId, locationDto.location)
}
// delete()
@Test
override fun `deleteById() deletes the entity with the given id in the repository`() {
whenever(repository.canBeDeleted(entity.id!!)).doReturn(true)
super.`deleteById() deletes the entity with the given id in the repository`()
}
}
@ -212,7 +232,7 @@ data class MixUpdateDtoTestScope(
id = 0L,
name = null,
materialTypeId = null,
mixMaterials = mutableMapOf()
mixMaterials = setOf()
)
)
)

View File

@ -1,10 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
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 dev.fyloz.colorrecipesexplorer.exception.EntityAlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixTypeRepository
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows

View File

@ -1,10 +1,10 @@
package dev.fyloz.trial.colorrecipesexplorer.service
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.trial.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository
import dev.fyloz.trial.colorrecipesexplorer.service.files.FileService
import dev.fyloz.colorrecipesexplorer.exception.EntityNotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.RecipeRepository
import dev.fyloz.colorrecipesexplorer.service.files.FileService
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
@ -20,8 +20,8 @@ class RecipeServiceTest :
override val repository: RecipeRepository = mock()
private val companyService: CompanyService = mock()
private val mixService: MixService = mock()
private val stepService: RecipeStepService = mock()
override val service: RecipeService = spy(RecipeServiceImpl(repository, companyService, mixService, stepService))
private val groupService: EmployeeGroupService = mock()
override val service: RecipeService = spy(RecipeServiceImpl(repository, companyService, mixService, groupService))
private val company: Company = company(id = 0L)
override val entity: Recipe = recipe(id = 0L, name = "recipe", company = company)
@ -31,11 +31,10 @@ class RecipeServiceTest :
@AfterEach
override fun afterEach() {
reset(companyService, mixService, stepService)
reset(companyService, mixService)
super.afterEach()
}
// existsByCompany()
@Test
@ -77,67 +76,53 @@ class RecipeServiceTest :
}
// update()
@Test
override fun `update(dto) calls and returns update() with the created entity`() =
withBaseUpdateDtoTest(entity, entityUpdateDto, service, { any() })
@Test
fun `update(dto) remove unused steps`() {
val steps = listOf(
recipeStep(message = "step 1"),
recipeStep(message = "step 2"),
recipeStep(message = "step 3"),
recipeStep(message = "step 4"),
recipeStep(message = "step 5"),
recipeStep(message = "step 6"),
recipeStep(message = "step 7"),
recipeStep(message = "step 8")
)
val originalSteps = steps.subList(0, 5)
val updatedSteps = steps.subList(2, 7)
val deletedSteps = steps.subList(0, 1)
val recipe = recipe(id = 0L, steps = originalSteps)
val dto = spy(recipeUpdateDto(id = recipe.id!!, steps = updatedSteps))
doAnswer { it.arguments[0] }.whenever(service).update(any<Recipe>())
doReturn(recipe).whenever(dto).toEntity()
doReturn(recipe).whenever(service).getById(recipe.id!!)
doReturn(true).whenever(service).existsById(recipe.id!!)
val found = service.update(dto)
verify(stepService).delete(argThat { this in deletedSteps })
updatedSteps.forEach {
assertTrue { found.steps.any { step -> step.message == it.message } }
}
}
// updatePublicData()
@Test
fun `updatePublicData() calls update with the updated note`() {
val publicDataDto = recipePublicDataDto(id = entity.id!!, note = "newNote", mixesLocation = null)
val expected = entity.apply { note = publicDataDto.note!! }
doReturn(entity).whenever(service).getById(entity.id!!)
doReturn(expected).whenever(service).update(expected)
fun `updatePublicData() updates the notes of a recipe groups information according to the RecipePublicDataDto`() {
val recipe = recipe(
id = 0L, groupsInformation = setOf(
recipeGroupInformation(id = 0L, group = employeeGroup(id = 1L), note = "Old note"),
recipeGroupInformation(id = 1L, group = employeeGroup(id = 2L), note = "Another note"),
recipeGroupInformation(id = 2L, group = employeeGroup(id = 3L), note = "Up to date note")
)
)
val notes = setOf(
noteDto(groupId = 1, content = "Note 1"),
noteDto(groupId = 2, content = null)
)
val publicData = recipePublicDataDto(recipeId = recipe.id!!, notes = notes)
service.updatePublicData(publicDataDto)
doReturn(recipe).whenever(service).getById(recipe.id!!)
doAnswer { it.arguments[0] }.whenever(service).update(any<Recipe>())
verify(service).update(expected)
service.updatePublicData(publicData)
verify(service).update(argThat<Recipe> {
assertTrue { this.groupsInformation.first { it.group.id == 1L }.note == notes.first { it.groupId == 1L }.content }
assertTrue { this.groupsInformation.first { it.group.id == 2L }.note == notes.first { it.groupId == 2L }.content }
assertTrue { this.groupsInformation.any { it.group.id == 3L } && this.groupsInformation.first { it.group.id == 3L }.note == null }
true
})
verify(mixService, times(0)).updateLocations(any())
}
@Test
fun `updatePublicData() calls mixService_updateLocation() with every mix and locations`() {
val mix = mix(id = 0L)
val mixRecipe = entity.apply { mixes.add(mix) }
val location = "location"
val mixLocation = mapOf(mix.id!! to location)
val publicDataDto = recipePublicDataDto(id = mixRecipe.id!!, note = null, mixesLocation = mixLocation)
doReturn(mixRecipe).whenever(service).getById(mixRecipe.id!!)
fun `updatePublicData() update the location of a recipe mixes in the mix service according to the RecipePublicDataDto`() {
val publicData = recipePublicDataDto(mixesLocation = setOf(
mixLocationDto(mixId = 0L, location = "Loc 1"),
mixLocationDto(mixId = 1L, location = "Loc 2")
))
service.updatePublicData(publicDataDto)
service.updatePublicData(publicData)
verify(mixService).updateLocation(mix, location)
verify(mixService).updateLocations(publicData.mixesLocation!!)
verify(service, times(0)).update(any<Recipe>())
}
// addMix()

View File

@ -0,0 +1,16 @@
package dev.fyloz.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.spy
import dev.fyloz.colorrecipesexplorer.model.RecipeStep
import dev.fyloz.colorrecipesexplorer.model.recipeStep
import dev.fyloz.colorrecipesexplorer.repository.RecipeStepRepository
class RecipeStepServiceTest :
AbstractModelServiceTest<RecipeStep, RecipeStepService, RecipeStepRepository>() {
override val repository: RecipeStepRepository = mock()
override val service: RecipeStepService = spy(RecipeStepServiceImpl(repository))
override val entity: RecipeStep = recipeStep(id = 0L, message = "message")
override val anotherEntity: RecipeStep = recipeStep(id = 1L, message = "another message")
}

View File

@ -1,44 +0,0 @@
package dev.fyloz.trial.colorrecipesexplorer.service
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.spy
import dev.fyloz.trial.colorrecipesexplorer.model.*
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeStepRepository
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class RecipeStepServiceTest :
AbstractModelServiceTest<RecipeStep, RecipeStepService, RecipeStepRepository>() {
override val repository: RecipeStepRepository = mock()
override val service: RecipeStepService = spy(RecipeStepServiceImpl(repository))
override val entity: RecipeStep = recipeStep(id = 0L, recipe = recipe(id = 0L), message = "message")
override val anotherEntity: RecipeStep = recipeStep(id = 1L, recipe = recipe(id = 1L), message = "another message")
// createForRecipe()
@Test
fun `createForRecipe() returns a correct RecipeStep`() {
val step = recipeStep(null, entity.recipe, entity.message)
val found = service.createForRecipe(entity.recipe!!, entity.message)
assertEquals(step, found)
}
// createAllForRecipe()
@Test
fun `createAllForRecipe() returns all correct RecipeSteps`() {
val steps = listOf(
recipeStep(null, entity.recipe, entity.message),
recipeStep(null, entity.recipe, anotherEntity.message)
)
val messages = steps.map { it.message }
val found = service.createAllForRecipe(entity.recipe!!, messages)
assertEquals(steps, found)
}
}