Ajout d'un endpoint REST permettant de mettre à jour les informations publiques d'une recette.
This commit is contained in:
parent
04e7049e2e
commit
c2c58be6bf
|
@ -1,59 +0,0 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.model;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Mix implements Model {
|
||||
|
||||
public static final String IDENTIFIER_MIX_TYPE_NAME = "mixType";
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
@Basic
|
||||
private Long id;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private Recipe recipe;
|
||||
|
||||
@NonNull
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private MixType mixType;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "mix")
|
||||
private List<MixMaterial> mixMaterials;
|
||||
|
||||
// Casier
|
||||
private String location;
|
||||
|
||||
public MixType getMixType() {
|
||||
return mixType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Mix mix = (Mix) o;
|
||||
return Objects.equals(recipe, mix.recipe) &&
|
||||
Objects.equals(mixType, mix.mixType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(recipe, mixType);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.repository;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface MixRepository extends JpaRepository<Mix, Long> {
|
||||
|
||||
List<Mix> findAllByRecipe(Recipe recipe);
|
||||
|
||||
}
|
|
@ -4,9 +4,9 @@ import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsE
|
|||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.AbstractJavaService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.utils.MixBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -16,13 +16,13 @@ import java.util.Comparator;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class MixService extends AbstractJavaService<Mix, MixRepository> {
|
||||
public class MixJavaService extends AbstractJavaService<Mix, MixRepository> {
|
||||
|
||||
private MaterialJavaService materialService;
|
||||
private MixMaterialJavaService mixQuantityService;
|
||||
private MixTypeJavaService mixTypeService;
|
||||
|
||||
public MixService() {
|
||||
public MixJavaService() {
|
||||
super(Mix.class);
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ public class MixService extends AbstractJavaService<Mix, MixRepository> {
|
|||
.build();
|
||||
|
||||
if (mix.getRecipe().containsMixType(mix.getMixType()))
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, Mix.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixKt.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
|
||||
|
||||
mixTypeService.save(mix.getMixType());
|
||||
save(mix);
|
||||
|
@ -112,7 +112,7 @@ public class MixService extends AbstractJavaService<Mix, MixRepository> {
|
|||
MixType mixType = mix.getMixType();
|
||||
|
||||
if (!formDto.getOldMixTypeName().equals(mixType.getName()) && mixTypeService.existsByName(formDto.getMixTypeName()) && mix.getRecipe().containsMixType(mixType))
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, Mix.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixKt.IDENTIFIER_MIX_TYPE_NAME, mix.getMixType().getName());
|
||||
|
||||
if (materialService.existsByName(mixType.getName()) && !materialService.getByName(mixType.getName()).isMixType())
|
||||
throw new EntityAlreadyExistsException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, mixType.getName());
|
|
@ -20,7 +20,7 @@ import java.util.stream.Collectors;
|
|||
public class RecipeJavaService extends AbstractJavaService<Recipe, RecipeRepository> {
|
||||
|
||||
private CompanyJavaService companyService;
|
||||
private MixService mixService;
|
||||
private MixJavaService mixService;
|
||||
private RecipeStepJavaService stepService;
|
||||
private ImagesService imagesService;
|
||||
|
||||
|
@ -39,7 +39,7 @@ public class RecipeJavaService extends AbstractJavaService<Recipe, RecipeReposit
|
|||
}
|
||||
|
||||
@Autowired
|
||||
public void setMixService(MixService mixService) {
|
||||
public void setMixService(MixJavaService mixService) {
|
||||
this.mixService = mixService;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import dev.fyloz.trial.colorrecipesexplorer.model.*;
|
|||
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixTypeJavaService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -17,7 +16,7 @@ public class MixBuilder {
|
|||
private Recipe recipe;
|
||||
private MixType mixType;
|
||||
private String location;
|
||||
private List<MixMaterial> mixQuantities = new ArrayList<>();
|
||||
private Collection<MixMaterial> mixMaterials = new ArrayList<>();
|
||||
|
||||
private Map<String, Float> quantities = new LinkedHashMap<>();
|
||||
|
||||
|
@ -31,7 +30,7 @@ public class MixBuilder {
|
|||
this.recipe = mix.getRecipe();
|
||||
this.mixType = mix.getMixType();
|
||||
this.location = mix.getLocation();
|
||||
this.mixQuantities = mix.getMixMaterials();
|
||||
this.mixMaterials = mix.getMixMaterials();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -82,25 +81,22 @@ public class MixBuilder {
|
|||
}
|
||||
|
||||
public MixBuilder withMixQuantity(MixMaterial mixMaterial) {
|
||||
this.mixQuantities.add(mixMaterial);
|
||||
this.mixMaterials.add(mixMaterial);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MixBuilder withMixQuantities(List<MixMaterial> mixQuantities) {
|
||||
this.mixQuantities = mixQuantities;
|
||||
this.mixMaterials = mixQuantities;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Mix build() {
|
||||
Mix mix = new Mix(this.recipe, this.mixType);
|
||||
Mix mix = new Mix(this.id, this.location, this.recipe, this.mixType, new ArrayList<>());
|
||||
|
||||
createMixQuantities(mix);
|
||||
|
||||
mix.setId(this.id);
|
||||
mix.setLocation(this.location);
|
||||
mix.setMixMaterials(this.mixQuantities);
|
||||
mix.getMixMaterials().addAll(this.mixMaterials);
|
||||
|
||||
return mix;
|
||||
}
|
||||
|
@ -115,6 +111,6 @@ public class MixBuilder {
|
|||
mixQuantities.add(new MixMaterial(mix, material, quantity));
|
||||
}
|
||||
|
||||
this.mixQuantities = mixQuantities;
|
||||
this.mixMaterials = mixQuantities;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundExcept
|
|||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.files.MarkdownFilesService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixJavaService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
@ -24,12 +24,12 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
|||
@Profile("thymeleaf")
|
||||
public class OthersController {
|
||||
|
||||
private MixService mixService;
|
||||
private MixJavaService mixService;
|
||||
private RecipeJavaService recipeService;
|
||||
private MarkdownFilesService markdownService;
|
||||
|
||||
@Autowired
|
||||
public OthersController(MixService mixService, RecipeJavaService recipeService, MarkdownFilesService markdownService) {
|
||||
public OthersController(MixJavaService mixService, RecipeJavaService recipeService, MarkdownFilesService markdownService) {
|
||||
this.mixService = mixService;
|
||||
this.recipeService = recipeService;
|
||||
this.markdownService = markdownService;
|
||||
|
|
|
@ -2,12 +2,12 @@ package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.creators;
|
|||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixKt;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.ServiceKt;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.*;
|
||||
|
@ -29,13 +29,13 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
|||
@Profile("thymeleaf")
|
||||
public class MixCreatorController {
|
||||
|
||||
private MixService mixService;
|
||||
private MixJavaService mixService;
|
||||
private RecipeJavaService recipeService;
|
||||
private MaterialJavaService materialService;
|
||||
private MaterialTypeJavaService materialTypeService;
|
||||
|
||||
@Autowired
|
||||
public MixCreatorController(MixService mixService, RecipeJavaService recipeService, MaterialJavaService materialService, MixTypeJavaService mixTypeService, MaterialTypeJavaService materialTypeService) {
|
||||
public MixCreatorController(MixJavaService mixService, RecipeJavaService recipeService, MaterialJavaService materialService, MixTypeJavaService mixTypeService, MaterialTypeJavaService materialTypeService) {
|
||||
this.mixService = mixService;
|
||||
this.recipeService = recipeService;
|
||||
this.materialService = materialService;
|
||||
|
@ -78,7 +78,7 @@ public class MixCreatorController {
|
|||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, ex.getRequestedId());
|
||||
} catch (EntityAlreadyExistsException ex) {
|
||||
if (ex.getIdentifierName().equals(Mix.IDENTIFIER_MIX_TYPE_NAME))
|
||||
if (ex.getIdentifierName().equals(MixKt.IDENTIFIER_MIX_TYPE_NAME))
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
|
||||
else if (ex.getIdentifierName().equals(MixTypeKt.IDENTIFIER_MATERIAL_NAME))
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
|
||||
|
|
|
@ -2,15 +2,16 @@ package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;
|
|||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixKt;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.MixTypeKt;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixJavaService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -26,12 +27,12 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
|||
@Profile("thymeleaf")
|
||||
public class MixEditorController {
|
||||
|
||||
private MixService mixService;
|
||||
private MixJavaService mixService;
|
||||
private MaterialJavaService materialService;
|
||||
private MaterialTypeJavaService materialTypeService;
|
||||
|
||||
@Autowired
|
||||
public MixEditorController(MixService mixService, MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
|
||||
public MixEditorController(MixJavaService mixService, MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
|
||||
this.mixService = mixService;
|
||||
this.materialService = materialService;
|
||||
this.materialTypeService = materialTypeService;
|
||||
|
@ -74,7 +75,7 @@ public class MixEditorController {
|
|||
} catch (EntityAlreadyExistsException ex) {
|
||||
if (ex.getIdentifierName().equals(MixTypeKt.IDENTIFIER_MATERIAL_NAME))
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
|
||||
else if (ex.getIdentifierName().equals(Mix.IDENTIFIER_MIX_TYPE_NAME))
|
||||
else if (ex.getIdentifierName().equals(MixKt.IDENTIFIER_MIX_TYPE_NAME))
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
|
||||
else throw new EntityAlreadyExistsException(ex);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.removers;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.model.MixJavaService;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -17,9 +17,9 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
|||
@Profile("thymeleaf")
|
||||
public class MixRemoverController {
|
||||
|
||||
private MixService mixService;
|
||||
private MixJavaService mixService;
|
||||
|
||||
public MixRemoverController(MixService mixService) {
|
||||
public MixRemoverController(MixJavaService mixService) {
|
||||
this.mixService = mixService;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.model
|
||||
|
||||
import java.util.*
|
||||
import javax.persistence.*
|
||||
|
||||
const val IDENTIFIER_MIX_TYPE_NAME = "mixType"
|
||||
|
||||
@Entity
|
||||
data class Mix(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
override val id: Long?,
|
||||
|
||||
var location: String?,
|
||||
|
||||
@ManyToOne
|
||||
val recipe: Recipe,
|
||||
|
||||
@ManyToOne
|
||||
val mixType: MixType,
|
||||
|
||||
@OneToMany
|
||||
val mixMaterials: Collection<MixMaterial>,
|
||||
) : Model {
|
||||
constructor(recipe: Recipe, mixType: MixType) : this(null, null, recipe, mixType, listOf())
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is Mix && recipe == other.recipe && mixType == other.mixType
|
||||
override fun hashCode(): Int = Objects.hash(recipe, mixType)
|
||||
}
|
||||
|
||||
// ==== DSL ====
|
||||
fun mix(
|
||||
id: Long? = null,
|
||||
location: String = "location",
|
||||
recipe: Recipe = recipe(),
|
||||
mixType: MixType = mixType(),
|
||||
mixMaterials: Collection<MixMaterial> = listOf(),
|
||||
op: Mix.() -> Unit = {}
|
||||
) = Mix(id, location, recipe, mixType, mixMaterials).apply(op)
|
|
@ -44,10 +44,10 @@ data class Recipe(
|
|||
|
||||
@JsonIgnore
|
||||
@OneToMany
|
||||
val mixes: List<Mix>,
|
||||
val mixes: MutableCollection<Mix>,
|
||||
|
||||
@OneToMany
|
||||
var steps: List<RecipeStep>
|
||||
@OneToMany(cascade = [CascadeType.ALL])
|
||||
var steps: MutableCollection<RecipeStep>
|
||||
) : Model {
|
||||
constructor(
|
||||
id: Long,
|
||||
|
@ -58,7 +58,7 @@ data class Recipe(
|
|||
approbationDate: LocalDate?,
|
||||
remark: String,
|
||||
note: String
|
||||
) : this(id, name, description, sample, approbationDate, remark, note, company, listOf(), listOf())
|
||||
) : this(id, name, description, sample, approbationDate, remark, note, company, mutableListOf(), mutableListOf())
|
||||
|
||||
val mixesSortedById: Collection<Mix>
|
||||
@JsonIgnore
|
||||
|
@ -67,7 +67,7 @@ data class Recipe(
|
|||
/** The mix types contained in this recipe. */
|
||||
val mixTypes: Collection<MixType>
|
||||
@JsonIgnore
|
||||
get() = mixes.map { it.getMixType() as MixType }
|
||||
get() = mixes.map { it.mixType }
|
||||
|
||||
/** Checks if the recipe contains the given [mixType]. */
|
||||
fun containsMixType(mixType: MixType) = mixTypes.contains(mixType)
|
||||
|
@ -76,6 +76,15 @@ data class Recipe(
|
|||
override fun hashCode(): Int = Objects.hash(name, company)
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -106,22 +115,22 @@ open class RecipeSaveDto(
|
|||
|
||||
open class RecipeUpdateDto(
|
||||
@field:NotNull(message = RECIPE_ID_NULL_MESSAGE)
|
||||
val id: Long = 0L,
|
||||
val id: Long,
|
||||
|
||||
@field:NullOrNotBlank(message = RECIPE_NAME_NULL_MESSAGE)
|
||||
val name: String? = "name",
|
||||
val name: String?,
|
||||
|
||||
@field:NullOrNotBlank(message = RECIPE_DESCRIPTION_NULL_MESSAGE)
|
||||
val description: String? = "description",
|
||||
val description: String?,
|
||||
|
||||
@field:NullOrSize(min = 0, message = RECIPE_SAMPLE_TOO_SMALL_MESSAGE)
|
||||
val sample: Int? = -1,
|
||||
val sample: Int?,
|
||||
|
||||
val approbationDate: LocalDate? = LocalDate.MIN,
|
||||
val approbationDate: LocalDate?,
|
||||
|
||||
val remark: String? = "remark",
|
||||
val remark: String?,
|
||||
|
||||
val steps: List<RecipeStep>? = listOf()
|
||||
val steps: List<RecipeStep>?
|
||||
) : EntityDto<Recipe> {
|
||||
override fun toEntity(): Recipe = recipe(
|
||||
id,
|
||||
|
@ -130,7 +139,7 @@ open class RecipeUpdateDto(
|
|||
sample = sample ?: -1,
|
||||
approbationDate = approbationDate ?: LocalDate.MIN,
|
||||
remark = remark ?: "remark",
|
||||
steps = steps ?: listOf()
|
||||
steps = steps?.toMutableList() ?: mutableListOf()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -144,11 +153,18 @@ fun recipe(
|
|||
remark: String = "remark",
|
||||
note: String = "",
|
||||
company: Company = company(),
|
||||
mixes: List<Mix> = listOf(),
|
||||
steps: List<RecipeStep> = listOf(),
|
||||
mixes: MutableCollection<Mix> = mutableListOf(),
|
||||
steps: MutableCollection<RecipeStep> = mutableListOf(),
|
||||
op: Recipe.() -> Unit = {}
|
||||
) = Recipe(id, name, description, 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)
|
||||
|
||||
fun recipeSaveDto(
|
||||
name: String = "name",
|
||||
description: String = "description",
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.repository
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface MixRepository : JpaRepository<Mix, Long>
|
|
@ -1,20 +1,30 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.rest
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.RecipePublicDataDto
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeSaveDto
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.RecipeUpdateDto
|
||||
import dev.fyloz.trial.colorrecipesexplorer.service.RecipeService
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.PutMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import javax.validation.Valid
|
||||
|
||||
|
||||
private const val RECIPE_CONTROLLER_PATH = "api/recipe"
|
||||
|
||||
@RestController
|
||||
@RequestMapping(RECIPE_CONTROLLER_PATH)
|
||||
|
||||
class RecipeController(recipeService: RecipeService) :
|
||||
AbstractModelRestApiController<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeService>(
|
||||
recipeService,
|
||||
RECIPE_CONTROLLER_PATH
|
||||
)
|
||||
) {
|
||||
@PutMapping("public")
|
||||
fun updatePublicData(@Valid @RequestBody publicDataDto: RecipePublicDataDto): ResponseEntity<Void> {
|
||||
service.updatePublicData(publicDataDto)
|
||||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
interface MixService : ModelService<Mix, MixRepository> {
|
||||
/** Updates the location of the given [mix] to the given [location]. */
|
||||
fun updateLocation(mix: Mix, location: String)
|
||||
}
|
||||
|
||||
@Service
|
||||
class MixServiceImpl(mixRepository: MixRepository) : AbstractModelService<Mix, MixRepository>(mixRepository),
|
||||
MixService {
|
||||
override fun updateLocation(mix: Mix, location: String) {
|
||||
update(mix.apply { this.location = location })
|
||||
}
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.isNotNullAndNotBlank
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.isNullOrNotBlank
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.validation.or
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository
|
||||
import org.springframework.stereotype.Service
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
interface RecipeService : ExternalModelService<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeRepository> {
|
||||
/** Checks if one or more recipes have the given [company]. */
|
||||
|
@ -12,16 +15,24 @@ interface RecipeService : ExternalModelService<Recipe, RecipeSaveDto, RecipeUpda
|
|||
|
||||
/** Gets all recipes with the given [company]. */
|
||||
fun getAllByCompany(company: Company): Collection<Recipe>
|
||||
|
||||
/** Updates the public data of a recipe with the given [publicDateDto]. */
|
||||
fun updatePublicData(publicDataDto: RecipePublicDataDto)
|
||||
}
|
||||
|
||||
@Service
|
||||
class RecipeServiceImpl(recipeRepository: RecipeRepository, val companyService: CompanyService) :
|
||||
class RecipeServiceImpl(
|
||||
recipeRepository: RecipeRepository,
|
||||
val companyService: CompanyService,
|
||||
val mixService: MixService
|
||||
) :
|
||||
AbstractExternalModelService<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeRepository>(recipeRepository),
|
||||
RecipeService {
|
||||
override fun existsByCompany(company: Company): Boolean = repository.existsByCompany(company)
|
||||
override fun getAllByCompany(company: Company): Collection<Recipe> = repository.findAllByCompany(company)
|
||||
|
||||
override fun save(entity: RecipeSaveDto): Recipe {
|
||||
// TODO checks if name is unique in the scope of the [company]
|
||||
return save(with(entity) {
|
||||
recipe(
|
||||
name = name,
|
||||
|
@ -49,8 +60,27 @@ class RecipeServiceImpl(recipeRepository: RecipeRepository, val companyService:
|
|||
note = persistedRecipe.note,
|
||||
company = persistedRecipe.company,
|
||||
mixes = persistedRecipe.mixes,
|
||||
steps = if (!steps.isNullOrEmpty()) steps else persistedRecipe.steps
|
||||
steps = steps?.toMutableList() ?: persistedRecipe.steps
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.Mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.mix
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class MixServiceTest : AbstractModelServiceTest<Mix, MixService, MixRepository>() {
|
||||
override val repository: MixRepository = mock()
|
||||
override val service: MixService = spy(MixServiceImpl(repository))
|
||||
|
||||
override val entity: Mix = mix(id = 0L, location = "location")
|
||||
override val anotherEntity: Mix = mix(id = 1L)
|
||||
|
||||
@Nested
|
||||
inner class UpdateLocation {
|
||||
@Test
|
||||
fun `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)
|
||||
|
||||
service.updateLocation(entity, newLocation)
|
||||
|
||||
verify(service).update(expected)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.service
|
||||
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.spy
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository
|
||||
import org.junit.jupiter.api.Nested
|
||||
|
@ -16,7 +13,8 @@ class RecipeServiceTest :
|
|||
AbstractExternalModelServiceTest<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeService, RecipeRepository>() {
|
||||
override val repository: RecipeRepository = mock()
|
||||
private val companyService: CompanyService = mock()
|
||||
override val service: RecipeService = spy(RecipeServiceImpl(repository, companyService))
|
||||
private val mixService: MixService = mock()
|
||||
override val service: RecipeService = spy(RecipeServiceImpl(repository, companyService, mixService))
|
||||
|
||||
private val company: Company = company(id = 0L)
|
||||
override val entity: Recipe = recipe(id = 0L, name = "recipe", company = company)
|
||||
|
@ -66,4 +64,33 @@ class RecipeServiceTest :
|
|||
saveDtoTest(entity, entitySaveDto, service)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdatePublicDate {
|
||||
@Test
|
||||
fun `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)
|
||||
|
||||
service.updatePublicData(publicDataDto)
|
||||
|
||||
verify(service).update(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `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!!)
|
||||
|
||||
service.updatePublicData(publicDataDto)
|
||||
|
||||
verify(mixService).updateLocation(mix, location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue