diff --git a/codiki-application/src/main/java/org/codiki/application/category/CategoryUseCases.java b/codiki-application/src/main/java/org/codiki/application/category/CategoryUseCases.java index 6a0ac82..84324c5 100644 --- a/codiki-application/src/main/java/org/codiki/application/category/CategoryUseCases.java +++ b/codiki-application/src/main/java/org/codiki/application/category/CategoryUseCases.java @@ -68,11 +68,14 @@ public class CategoryUseCases { } if (!isNull(subCategoryIds)) { - List subCategories; - try { - subCategories = categoryPort.findAllByIds(subCategoryIds); - } catch (CategoryNotFoundException exception) { - throw new CategoryEditionException(exception); + List subCategories = emptyList(); + + if (!subCategoryIds.isEmpty()) { + try { + subCategories = categoryPort.findAllByIds(subCategoryIds); + } catch (CategoryNotFoundException exception) { + throw new CategoryEditionException(exception); + } } categoryBuilder.withSubCategories(subCategories); } @@ -93,4 +96,8 @@ public class CategoryUseCases { categoryPort.deleteById(categoryId); } + + public List getAll() { + return categoryPort.findAll(); + } } diff --git a/codiki-domain/src/main/java/org/codiki/domain/category/port/CategoryPort.java b/codiki-domain/src/main/java/org/codiki/domain/category/port/CategoryPort.java index c018b7f..ae3b00a 100644 --- a/codiki-domain/src/main/java/org/codiki/domain/category/port/CategoryPort.java +++ b/codiki-domain/src/main/java/org/codiki/domain/category/port/CategoryPort.java @@ -18,4 +18,6 @@ public interface CategoryPort { void deleteById(UUID categoryId); boolean existsById(UUID categoryId); + + List findAll(); } diff --git a/codiki-exposition/src/main/java/org/codiki/exposition/category/CategoryController.java b/codiki-exposition/src/main/java/org/codiki/exposition/category/CategoryController.java index c612d75..4ac725b 100644 --- a/codiki-exposition/src/main/java/org/codiki/exposition/category/CategoryController.java +++ b/codiki-exposition/src/main/java/org/codiki/exposition/category/CategoryController.java @@ -1,5 +1,6 @@ package org.codiki.exposition.category; +import java.util.List; import java.util.UUID; 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.CategoryEditionRequest; 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.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -51,4 +53,12 @@ public class CategoryController { public void deleteCategory(@PathVariable("categoryId") UUID categoryId) { categoryUseCases.deleteCategory(categoryId); } + + @GetMapping + public List getAllCategories() { + return categoryUseCases.getAll() + .stream() + .map(CategoryDto::new) + .toList(); + } } diff --git a/codiki-exposition/src/main/java/org/codiki/exposition/configuration/security/SecurityConfiguration.java b/codiki-exposition/src/main/java/org/codiki/exposition/configuration/security/SecurityConfiguration.java index 8ae4309..f2bcbff 100644 --- a/codiki-exposition/src/main/java/org/codiki/exposition/configuration/security/SecurityConfiguration.java +++ b/codiki-exposition/src/main/java/org/codiki/exposition/configuration/security/SecurityConfiguration.java @@ -43,6 +43,7 @@ public class SecurityConfiguration { .requestMatchers( GET, "/api/health/check", + "/api/categories", "/error" ).permitAll() .requestMatchers( diff --git a/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/CategoryJpaAdapter.java b/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/CategoryJpaAdapter.java index c875963..71f1f4d 100644 --- a/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/CategoryJpaAdapter.java +++ b/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/CategoryJpaAdapter.java @@ -38,10 +38,9 @@ public class CategoryJpaAdapter implements CategoryPort { .map(CategoryEntity::toDomain) .toList(); - Optional notFoundCategoryId = categories.stream() - .filter(category -> !categoryIds.contains(category.id())) - .findFirst() - .map(Category::id); + Optional notFoundCategoryId = categoryIds.stream() + .filter(categoryId -> categories.stream().map(Category::id).noneMatch(categoryId::equals)) + .findFirst(); if (notFoundCategoryId.isPresent()) { throw new CategoryNotFoundException(notFoundCategoryId.get()); } @@ -62,4 +61,12 @@ public class CategoryJpaAdapter implements CategoryPort { public boolean existsById(UUID categoryId) { return categoryRepository.existsById(categoryId); } + + @Override + public List findAll() { + return categoryRepository.findAll() + .stream() + .map(CategoryEntity::toDomain) + .toList(); + } } diff --git a/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/model/CategoryEntity.java b/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/model/CategoryEntity.java index f5032c2..f0eb55f 100644 --- a/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/model/CategoryEntity.java +++ b/codiki-infrastructure/src/main/java/org/codiki/infrastructure/category/model/CategoryEntity.java @@ -1,13 +1,24 @@ package org.codiki.infrastructure.category.model; 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.stream.Collectors; 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.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Getter; @@ -25,12 +36,18 @@ public class CategoryEntity { private UUID id; @Column(nullable = false) private String name; -// List subCategories + @OneToMany + @JoinColumn(name = "parent_category_id") + private Set subCategories; public CategoryEntity(Category category) { this( category.id(), - category.name() + category.name(), + category.subCategories() + .stream() + .map(CategoryEntity::new) + .collect(toSet()) ); } @@ -38,7 +55,9 @@ public class CategoryEntity { return new Category( id, name, - emptyList() + subCategories.stream() + .map(CategoryEntity::toDomain) + .toList() ); } } diff --git a/codiki-infrastructure/src/main/resources/sql/001-initial-script-tables-creation.sql b/codiki-infrastructure/src/main/resources/sql/001-initial-script-tables-creation.sql index 2a6866d..6cea0b3 100644 --- a/codiki-infrastructure/src/main/resources/sql/001-initial-script-tables-creation.sql +++ b/codiki-infrastructure/src/main/resources/sql/001-initial-script-tables-creation.sql @@ -25,8 +25,11 @@ CREATE INDEX refresh_token_fk_user_id_idx ON user_role (user_id); CREATE TABLE IF NOT EXISTS category ( id UUID 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 ( id UUID NOT NULL, diff --git a/rest-client-collection/Codiki/environments/localhost.bru b/rest-client-collection/Codiki/environments/localhost.bru index 66412d7..d5669d1 100644 --- a/rest-client-collection/Codiki/environments/localhost.bru +++ b/rest-client-collection/Codiki/environments/localhost.bru @@ -1,6 +1,6 @@ vars { url: http://localhost:8080 publicationId: fce1de27-11c6-4deb-a248-b63288c00037 - bearerToken: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxNWExM2RjNy0wMjlkLTRlYWItYTYzZC1jMWU5NmY5MDI0MWQiLCJleHAiOjE3MTAyNjMyOTh9.j-PRoIYVjPcpaE92u8sEUsZib1mGTrZmfd96ZgnGgskUqhnoUtCHwQbmbvHTdkr2XdypSU3Hq9dndwxU4ElmWA - categoryId: 872abbb4-a287-4519-8eeb-c43d567d89c8 + bearerToken: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxNWExM2RjNy0wMjlkLTRlYWItYTYzZC1jMWU5NmY5MDI0MWQiLCJleHAiOjE3MTAyNjU4MTZ9.t8tZce0gAXZ_DC2QEsdvJn6m-Ykjou1v4zDUIPWhzfWYR-JTeiFsfa68jkFwK2WT1aMvZppnVuc991g-yAjrPg + categoryId: 172fa901-3f4b-4540-92f3-1c15820e8ec9 }