Set up parent category mechanism.

This commit is contained in:
Florian THIERRY
2024-03-12 18:20:04 +01:00
parent a3295636b4
commit ed766d4c8c
8 changed files with 64 additions and 15 deletions

View File

@@ -68,11 +68,14 @@ public class CategoryUseCases {
} }
if (!isNull(subCategoryIds)) { if (!isNull(subCategoryIds)) {
List<Category> subCategories; List<Category> subCategories = emptyList();
try {
subCategories = categoryPort.findAllByIds(subCategoryIds); if (!subCategoryIds.isEmpty()) {
} catch (CategoryNotFoundException exception) { try {
throw new CategoryEditionException(exception); subCategories = categoryPort.findAllByIds(subCategoryIds);
} catch (CategoryNotFoundException exception) {
throw new CategoryEditionException(exception);
}
} }
categoryBuilder.withSubCategories(subCategories); categoryBuilder.withSubCategories(subCategories);
} }
@@ -93,4 +96,8 @@ public class CategoryUseCases {
categoryPort.deleteById(categoryId); categoryPort.deleteById(categoryId);
} }
public List<Category> getAll() {
return categoryPort.findAll();
}
} }

View File

@@ -18,4 +18,6 @@ public interface CategoryPort {
void deleteById(UUID categoryId); void deleteById(UUID categoryId);
boolean existsById(UUID categoryId); boolean existsById(UUID categoryId);
List<Category> findAll();
} }

View File

@@ -1,5 +1,6 @@
package org.codiki.exposition.category; package org.codiki.exposition.category;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.HttpStatus.CREATED;
@@ -9,6 +10,7 @@ import org.codiki.domain.category.model.Category;
import org.codiki.exposition.category.model.CategoryDto; import org.codiki.exposition.category.model.CategoryDto;
import org.codiki.exposition.category.model.CategoryEditionRequest; import org.codiki.exposition.category.model.CategoryEditionRequest;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
@@ -51,4 +53,12 @@ public class CategoryController {
public void deleteCategory(@PathVariable("categoryId") UUID categoryId) { public void deleteCategory(@PathVariable("categoryId") UUID categoryId) {
categoryUseCases.deleteCategory(categoryId); categoryUseCases.deleteCategory(categoryId);
} }
@GetMapping
public List<CategoryDto> getAllCategories() {
return categoryUseCases.getAll()
.stream()
.map(CategoryDto::new)
.toList();
}
} }

View File

@@ -43,6 +43,7 @@ public class SecurityConfiguration {
.requestMatchers( .requestMatchers(
GET, GET,
"/api/health/check", "/api/health/check",
"/api/categories",
"/error" "/error"
).permitAll() ).permitAll()
.requestMatchers( .requestMatchers(

View File

@@ -38,10 +38,9 @@ public class CategoryJpaAdapter implements CategoryPort {
.map(CategoryEntity::toDomain) .map(CategoryEntity::toDomain)
.toList(); .toList();
Optional<UUID> notFoundCategoryId = categories.stream() Optional<UUID> notFoundCategoryId = categoryIds.stream()
.filter(category -> !categoryIds.contains(category.id())) .filter(categoryId -> categories.stream().map(Category::id).noneMatch(categoryId::equals))
.findFirst() .findFirst();
.map(Category::id);
if (notFoundCategoryId.isPresent()) { if (notFoundCategoryId.isPresent()) {
throw new CategoryNotFoundException(notFoundCategoryId.get()); throw new CategoryNotFoundException(notFoundCategoryId.get());
} }
@@ -62,4 +61,12 @@ public class CategoryJpaAdapter implements CategoryPort {
public boolean existsById(UUID categoryId) { public boolean existsById(UUID categoryId) {
return categoryRepository.existsById(categoryId); return categoryRepository.existsById(categoryId);
} }
@Override
public List<Category> findAll() {
return categoryRepository.findAll()
.stream()
.map(CategoryEntity::toDomain)
.toList();
}
} }

View File

@@ -1,13 +1,24 @@
package org.codiki.infrastructure.category.model; package org.codiki.infrastructure.category.model;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toSet;
import java.util.List;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import org.codiki.domain.category.model.Category; import org.codiki.domain.category.model.Category;
import static jakarta.persistence.CascadeType.ALL;
import static jakarta.persistence.FetchType.LAZY;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@@ -25,12 +36,18 @@ public class CategoryEntity {
private UUID id; private UUID id;
@Column(nullable = false) @Column(nullable = false)
private String name; private String name;
// List<Category> subCategories @OneToMany
@JoinColumn(name = "parent_category_id")
private Set<CategoryEntity> subCategories;
public CategoryEntity(Category category) { public CategoryEntity(Category category) {
this( this(
category.id(), category.id(),
category.name() category.name(),
category.subCategories()
.stream()
.map(CategoryEntity::new)
.collect(toSet())
); );
} }
@@ -38,7 +55,9 @@ public class CategoryEntity {
return new Category( return new Category(
id, id,
name, name,
emptyList() subCategories.stream()
.map(CategoryEntity::toDomain)
.toList()
); );
} }
} }

View File

@@ -25,8 +25,11 @@ CREATE INDEX refresh_token_fk_user_id_idx ON user_role (user_id);
CREATE TABLE IF NOT EXISTS category ( CREATE TABLE IF NOT EXISTS category (
id UUID NOT NULL, id UUID NOT NULL,
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
CONSTRAINT category_pk PRIMARY KEY (id) parent_category_id UUID,
CONSTRAINT category_pk PRIMARY KEY (id),
CONSTRAINT category_parent_category_id_fk FOREIGN KEY (parent_category_id) REFERENCES category (id)
); );
CREATE INDEX category_parent_category_id_idx ON category (parent_category_id);
CREATE TABLE IF NOT EXISTS publication ( CREATE TABLE IF NOT EXISTS publication (
id UUID NOT NULL, id UUID NOT NULL,

View File

@@ -1,6 +1,6 @@
vars { vars {
url: http://localhost:8080 url: http://localhost:8080
publicationId: fce1de27-11c6-4deb-a248-b63288c00037 publicationId: fce1de27-11c6-4deb-a248-b63288c00037
bearerToken: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxNWExM2RjNy0wMjlkLTRlYWItYTYzZC1jMWU5NmY5MDI0MWQiLCJleHAiOjE3MTAyNjMyOTh9.j-PRoIYVjPcpaE92u8sEUsZib1mGTrZmfd96ZgnGgskUqhnoUtCHwQbmbvHTdkr2XdypSU3Hq9dndwxU4ElmWA bearerToken: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxNWExM2RjNy0wMjlkLTRlYWItYTYzZC1jMWU5NmY5MDI0MWQiLCJleHAiOjE3MTAyNjU4MTZ9.t8tZce0gAXZ_DC2QEsdvJn6m-Ykjou1v4zDUIPWhzfWYR-JTeiFsfa68jkFwK2WT1aMvZppnVuc991g-yAjrPg
categoryId: 872abbb4-a287-4519-8eeb-c43d567d89c8 categoryId: 172fa901-3f4b-4540-92f3-1c15820e8ec9
} }