diff --git a/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportCategoryRepositoryIntegrationTest.java b/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportCategoryRepositoryIntegrationTest.java new file mode 100644 index 0000000..580f3a1 --- /dev/null +++ b/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportCategoryRepositoryIntegrationTest.java @@ -0,0 +1,38 @@ +package org.openlmis.ao.reports.repository; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; +import org.openlmis.ao.testutils.EmbeddedReportCategoryDataBuilder; +import org.springframework.beans.factory.annotation.Autowired; + +public class EmbeddedReportCategoryRepositoryIntegrationTest extends + BaseCrudRepositoryIntegrationTest { + + private static final String NAME = "EmbeddedReportCategoryIntegrationTest"; + + @Autowired + private EmbeddedReportCategoryRepository embeddedReportCategoryRepository; + + @Override + EmbeddedReportCategoryRepository getRepository() { + return this.embeddedReportCategoryRepository; + } + + @Override + protected EmbeddedReportCategory generateInstance() { + return new EmbeddedReportCategoryDataBuilder().withName(NAME).buildAsNew(); + } + + @Test + public void shouldFindEmbeddedReportCategoryByName() { + embeddedReportCategoryRepository.save(generateInstance()); + + EmbeddedReportCategory found = embeddedReportCategoryRepository.findByName(NAME); + + assertThat(found.getName(), is(NAME)); + } + +} diff --git a/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportRepositoryIntegrationTest.java b/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportRepositoryIntegrationTest.java index 605e28d..a901130 100644 --- a/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportRepositoryIntegrationTest.java +++ b/src/integration-test/java/org/openlmis/ao/reports/repository/EmbeddedReportRepositoryIntegrationTest.java @@ -6,6 +6,8 @@ import java.util.List; import org.junit.Test; import org.openlmis.ao.reports.domain.EmbeddedReport; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; +import org.openlmis.ao.testutils.EmbeddedReportCategoryDataBuilder; import org.openlmis.ao.testutils.EmbeddedReportDataBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; @@ -21,6 +23,9 @@ public class EmbeddedReportRepositoryIntegrationTest extends @Autowired private EmbeddedReportRepository embeddedReportRepository; + @Autowired + private EmbeddedReportCategoryRepository embeddedReportCategoryRepository; + @Override EmbeddedReportRepository getRepository() { return this.embeddedReportRepository; @@ -28,7 +33,13 @@ EmbeddedReportRepository getRepository() { @Override protected EmbeddedReport generateInstance() { - return new EmbeddedReportDataBuilder().withName(NAME).buildAsNew(); + EmbeddedReportCategory category = embeddedReportCategoryRepository + .save(new EmbeddedReportCategoryDataBuilder().buildAsNew()); + + return new EmbeddedReportDataBuilder() + .withName(NAME) + .withCategory(category) + .buildAsNew(); } @Test @@ -43,19 +54,28 @@ public void shouldFindEmbeddedReportByName() { @Test public void shouldFindAllEmbeddedReportsByCategory() { Pageable pageable = new PageRequest(0, 2); + EmbeddedReportCategory defaultCategory = embeddedReportCategoryRepository.save( + new EmbeddedReportCategoryDataBuilder().withName(DEFAULT_CATEGORY).build() + ); + EmbeddedReportCategory uniqueCategory = embeddedReportCategoryRepository.save( + new EmbeddedReportCategoryDataBuilder().withName(UNIQUE_CATEGORY).build() + ); EmbeddedReport matchingReport1 = new EmbeddedReportDataBuilder() - .withCategory(DEFAULT_CATEGORY).build(); + .withCategory(defaultCategory) + .build(); EmbeddedReport matchingReport2 = new EmbeddedReportDataBuilder() - .withCategory(DEFAULT_CATEGORY).build(); + .withCategory(defaultCategory) + .build(); EmbeddedReport notMatchingReport = new EmbeddedReportDataBuilder() - .withCategory(UNIQUE_CATEGORY).build(); + .withCategory(uniqueCategory) + .build(); embeddedReportRepository.save(matchingReport1); embeddedReportRepository.save(matchingReport2); embeddedReportRepository.save(notMatchingReport); List found = - embeddedReportRepository.findAllByCategory(DEFAULT_CATEGORY, pageable).getContent(); + embeddedReportRepository.findAllByCategoryName(DEFAULT_CATEGORY, pageable).getContent(); assertThat(found.size(), is(2)); } diff --git a/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportCategoryControllerIntegrationTest.java b/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportCategoryControllerIntegrationTest.java new file mode 100644 index 0000000..9560592 --- /dev/null +++ b/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportCategoryControllerIntegrationTest.java @@ -0,0 +1,156 @@ +package org.openlmis.ao.reports.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.verify; + +import guru.nidi.ramltester.junit.RamlMatchers; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import org.junit.Before; +import org.junit.Test; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; +import org.openlmis.ao.reports.dto.EmbeddedReportCategoryDto; +import org.openlmis.ao.reports.repository.EmbeddedReportCategoryRepository; +import org.openlmis.ao.testutils.EmbeddedReportCategoryDataBuilder; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; + +@SuppressWarnings("PMD.TooManyMethods") +public class EmbeddedReportCategoryControllerIntegrationTest extends BaseWebIntegrationTest { + + private static final String RESOURCE_URL = "/api/reports/embeddedReportCategories"; + private static final String ID_URL = RESOURCE_URL + "/{id}"; + public static final String ID = "id"; + + @MockBean + private EmbeddedReportCategoryRepository embeddedReportCategoryRepository; + + @Before + public void setUp() { + mockUserAuthenticated(); + doNothing().when(permissionService).canViewEmbeddedReportsCategory(); + } + + @Test + public void shouldGetExistentEmbeddedReportCategory() { + // given + EmbeddedReportCategory embeddedReportCategory = + new EmbeddedReportCategoryDataBuilder().build(); + given(embeddedReportCategoryRepository.findOne(embeddedReportCategory.getId())) + .willReturn(embeddedReportCategory); + + // when + EmbeddedReportCategoryDto result = restAssured.given() + .queryParam(ACCESS_TOKEN, getToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .pathParam(ID, embeddedReportCategory.getId()) + .when() + .get(ID_URL) + .then() + .statusCode(200) + .extract().as(EmbeddedReportCategoryDto.class); + + // then + assertEquals(embeddedReportCategory.getId(), result.getId()); + assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); + } + + @Test + public void shouldNotGetNonExistentEmbeddedReportCategory() { + // given + given(embeddedReportCategoryRepository.findOne(anyUuid())).willReturn(null); + + // when + restAssured.given() + .queryParam(ACCESS_TOKEN, getToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .pathParam(ID, UUID.randomUUID()) + .when() + .get(ID_URL) + .then() + .statusCode(404); + + // then + assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); + } + + @Test + public void shouldGetAllEmbeddedReportCategories() { + // given + EmbeddedReportCategory category1 = new EmbeddedReportCategoryDataBuilder().build(); + EmbeddedReportCategory category2 = new EmbeddedReportCategoryDataBuilder().build(); + List categories = Arrays.asList(category1, category2); + + Pageable pageable = new PageRequest(0, categories.size()); + Page categoryPage = new PageImpl<>(categories, pageable, + categories.size()); + + given(embeddedReportCategoryRepository.findAll(pageable)).willReturn(categoryPage); + + // when + restAssured.given() + .queryParam(ACCESS_TOKEN, getToken()) + .queryParam("page", pageable.getPageNumber()) + .queryParam("size", pageable.getPageSize()) + .when() + .get(RESOURCE_URL) + .then() + .statusCode(200); + + // then + assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); + } + + @Test + public void shouldDeleteExistentEmbeddedReportCategory() { + // given + EmbeddedReportCategory embeddedReportCategory = + new EmbeddedReportCategoryDataBuilder().build(); + given(embeddedReportCategoryRepository.findOne(embeddedReportCategory.getId())) + .willReturn(embeddedReportCategory); + + // when + restAssured.given() + .queryParam(ACCESS_TOKEN, getToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .pathParam(ID, embeddedReportCategory.getId()) + .when() + .delete(ID_URL) + .then() + .statusCode(204); + + // then + verify(embeddedReportCategoryRepository, atLeastOnce()).delete(eq(embeddedReportCategory)); + assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); + } + + @Test + public void shouldNotDeleteNonExistentEmbeddedReportCategory() { + // given + given(embeddedReportCategoryRepository.findOne(anyUuid())).willReturn(null); + + // when + restAssured.given() + .queryParam(ACCESS_TOKEN, getToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .pathParam(ID, UUID.randomUUID()) + .when() + .delete(ID_URL) + .then() + .statusCode(404); + + // then + assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); + } + +} diff --git a/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportControllerIntegrationTest.java b/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportControllerIntegrationTest.java index 71b4c34..d4c7512 100644 --- a/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportControllerIntegrationTest.java +++ b/src/integration-test/java/org/openlmis/ao/reports/web/EmbeddedReportControllerIntegrationTest.java @@ -1,5 +1,6 @@ package org.openlmis.ao.reports.web; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; @@ -11,18 +12,24 @@ import guru.nidi.ramltester.junit.RamlMatchers; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.UUID; +import org.apache.http.HttpStatus; import org.junit.Before; import org.junit.Test; import org.openlmis.ao.reports.domain.EmbeddedReport; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; import org.openlmis.ao.reports.dto.EmbeddedReportDto; +import org.openlmis.ao.reports.repository.EmbeddedReportCategoryRepository; import org.openlmis.ao.reports.repository.EmbeddedReportRepository; +import org.openlmis.ao.testutils.EmbeddedReportCategoryDataBuilder; import org.openlmis.ao.testutils.EmbeddedReportDataBuilder; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @SuppressWarnings("PMD.TooManyMethods") @@ -30,10 +37,16 @@ public class EmbeddedReportControllerIntegrationTest extends BaseWebIntegrationT private static final String RESOURCE_URL = "/api/reports/embeddedReports"; private static final String ID_URL = RESOURCE_URL + "/{id}"; + public static final String ID = "id"; + public static final String NAME = "name"; + public static final String ENABLED = "enabled"; @MockBean private EmbeddedReportRepository embeddedReportRepository; + @MockBean + private EmbeddedReportCategoryRepository embeddedReportCategoryRepository; + @Before public void setUp() { mockUserAuthenticated(); @@ -43,14 +56,16 @@ public void setUp() { @Test public void shouldGetExistentEmbeddedReport() { // given - EmbeddedReport embeddedReport = new EmbeddedReportDataBuilder().build(); + EmbeddedReport embeddedReport = new EmbeddedReportDataBuilder() + .withCategory(new EmbeddedReportCategoryDataBuilder().build()) + .build(); given(embeddedReportRepository.findOne(embeddedReport.getId())).willReturn(embeddedReport); // when EmbeddedReportDto result = restAssured.given() .queryParam(ACCESS_TOKEN, getToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) - .pathParam("id", embeddedReport.getId()) + .pathParam(ID, embeddedReport.getId()) .when() .get(ID_URL) .then() @@ -71,7 +86,7 @@ public void shouldNotGetNonExistentEmbeddedReport() { restAssured.given() .queryParam(ACCESS_TOKEN, getToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) - .pathParam("id", UUID.randomUUID()) + .pathParam(ID, UUID.randomUUID()) .when() .get(ID_URL) .then() @@ -84,8 +99,12 @@ public void shouldNotGetNonExistentEmbeddedReport() { @Test public void shouldGetAllEmbeddedReports() { // given - EmbeddedReport report1 = new EmbeddedReportDataBuilder().build(); - EmbeddedReport report2 = new EmbeddedReportDataBuilder().build(); + EmbeddedReport report1 = new EmbeddedReportDataBuilder() + .withCategory(new EmbeddedReportCategoryDataBuilder().build()) + .build(); + EmbeddedReport report2 = new EmbeddedReportDataBuilder() + .withCategory(new EmbeddedReportCategoryDataBuilder().build()) + .build(); List reports = Arrays.asList(report1, report2); Pageable pageable = new PageRequest(0, reports.size()); @@ -117,7 +136,7 @@ public void shouldDeleteExistentEmbeddedReport() { restAssured.given() .queryParam(ACCESS_TOKEN, getToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) - .pathParam("id", embeddedReport.getId()) + .pathParam(ID, embeddedReport.getId()) .when() .delete(ID_URL) .then() @@ -137,7 +156,7 @@ public void shouldNotDeleteNonExistentEmbeddedReport() { restAssured.given() .queryParam(ACCESS_TOKEN, getToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) - .pathParam("id", UUID.randomUUID()) + .pathParam(ID, UUID.randomUUID()) .when() .delete(ID_URL) .then() @@ -147,4 +166,38 @@ public void shouldNotDeleteNonExistentEmbeddedReport() { assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); } + @Test + public void shouldUpdateEmbeddedReport() { + // given + EmbeddedReportCategory category = new EmbeddedReportCategoryDataBuilder().build(); + EmbeddedReport embeddedReport = new EmbeddedReportDataBuilder() + .withCategory(category) + .disabled() + .build(); + EmbeddedReportDto embeddedReportDto = EmbeddedReportDto.newInstance(embeddedReport); + embeddedReportDto.setName("new_name"); + given(embeddedReportRepository.findById(embeddedReport.getId())) + .willReturn(Optional.of(embeddedReport)); + given(embeddedReportCategoryRepository.findById(embeddedReport.getCategory().getId())) + .willReturn(Optional.of(category)); + + + // when + restAssured.given() + .queryParam(ACCESS_TOKEN, getToken()) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .pathParam(ID, embeddedReport.getId()) + .body(embeddedReportDto) + .when() + .put(ID_URL) + .then() + .statusCode(HttpStatus.SC_OK) + .body(NAME, is(embeddedReportDto.getName())) + .body(ENABLED, is(embeddedReportDto.isEnabled())); + + // then + assertThat(RAML_ASSERT_MESSAGE, restAssured.getLastReport(), RamlMatchers.hasNoViolations()); + } + } diff --git a/src/main/java/org/openlmis/ao/reports/domain/BaseEntity.java b/src/main/java/org/openlmis/ao/reports/domain/BaseEntity.java index 8c27076..4a9c4ec 100644 --- a/src/main/java/org/openlmis/ao/reports/domain/BaseEntity.java +++ b/src/main/java/org/openlmis/ao/reports/domain/BaseEntity.java @@ -18,6 +18,7 @@ @MappedSuperclass public abstract class BaseEntity { protected static final String TEXT_COLUMN_DEFINITION = "text"; + protected static final String BOOLEAN_COLUMN_DEFINITION = "boolean"; protected static final String UUID_COLUMN_DEFINITION = "pg-uuid"; @Id diff --git a/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReport.java b/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReport.java index d3d1a12..f2df264 100644 --- a/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReport.java +++ b/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReport.java @@ -18,6 +18,8 @@ import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; import java.util.UUID; import lombok.AllArgsConstructor; @@ -25,6 +27,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.openlmis.ao.reports.dto.EmbeddedReportDto; @Getter @Setter @@ -41,8 +44,12 @@ public class EmbeddedReport extends BaseEntity { @Column(columnDefinition = TEXT_COLUMN_DEFINITION) private String url; - @Column(columnDefinition = TEXT_COLUMN_DEFINITION) - private String category; + @ManyToOne + @JoinColumn(name = "categoryid") + private EmbeddedReportCategory category; + + @Column(columnDefinition = BOOLEAN_COLUMN_DEFINITION) + private boolean enabled; /** * Create a new instance of Embedded report based on data from {@link EmbeddedReport.Importer} @@ -56,7 +63,10 @@ public static EmbeddedReport newInstance(EmbeddedReport.Importer importer) { embeddedReport.setId(importer.getId()); embeddedReport.setName(importer.getName()); embeddedReport.setUrl(importer.getUrl()); - embeddedReport.setCategory(importer.getCategory()); + if (importer.getCategory() != null) { + embeddedReport.setCategory(EmbeddedReportCategory.newInstance(importer.getCategory())); + } + embeddedReport.setEnabled(importer.isEnabled()); return embeddedReport; } @@ -70,6 +80,18 @@ public void updateFrom(EmbeddedReport embeddedReport) { this.name = embeddedReport.getName(); this.url = embeddedReport.getUrl(); this.category = embeddedReport.getCategory(); + this.enabled = embeddedReport.isEnabled(); + } + + /** + * Copy values of attributes into new or updated Embedded Report. + * + * @param embeddedReportDto Embedded report with new values. + */ + public void updateFrom(EmbeddedReportDto embeddedReportDto) { + this.name = embeddedReportDto.getName(); + this.url = embeddedReportDto.getUrl(); + this.enabled = embeddedReportDto.isEnabled(); } /** @@ -82,6 +104,7 @@ public void export(EmbeddedReport.Exporter exporter) { exporter.setName(name); exporter.setUrl(url); exporter.setCategory(category); + exporter.setEnabled(enabled); } public interface Exporter { @@ -92,7 +115,9 @@ public interface Exporter { void setUrl(String url); - void setCategory(String category); + void setCategory(EmbeddedReportCategory category); + + void setEnabled(boolean enabled); } @@ -104,7 +129,9 @@ public interface Importer { String getUrl(); - String getCategory(); + EmbeddedReportCategory.Importer getCategory(); + + boolean isEnabled(); } diff --git a/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReportCategory.java b/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReportCategory.java new file mode 100644 index 0000000..2e42328 --- /dev/null +++ b/src/main/java/org/openlmis/ao/reports/domain/EmbeddedReportCategory.java @@ -0,0 +1,90 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2017 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  + * See the GNU Affero General Public License for more details. You should have received a copy of + * the GNU Affero General Public License along with this program. If not, see + * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.ao.reports.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "embedded_report_categories") +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class EmbeddedReportCategory extends BaseEntity { + + @Column(columnDefinition = TEXT_COLUMN_DEFINITION) + private String name; + + /** + * Create a new instance of Embedded report category based on data + * from {@link EmbeddedReportCategory.Importer} + * + * @param importer instance of {@link EmbeddedReportCategory.Importer} + * @return new instance of embedded report category. + */ + public static EmbeddedReportCategory newInstance(EmbeddedReportCategory.Importer importer) { + EmbeddedReportCategory category = new EmbeddedReportCategory(); + category.setId(importer.getId()); + category.updateFrom(importer); + + return category; + } + + /** + * Copy values of attributes into new or updated Embedded Report Category. + * + * @param importer Embedded report category importer with new values. + */ + public void updateFrom(EmbeddedReportCategory.Importer importer) { + this.name = importer.getName(); + } + + /** + * Export this object to the specified exporter (DTO). + * + * @param exporter exporter to export to + */ + public void export(EmbeddedReportCategory.Exporter exporter) { + exporter.setId(id); + exporter.setName(name); + } + + public interface Exporter { + + void setId(UUID id); + + void setName(String name); + + } + + public interface Importer { + + UUID getId(); + + String getName(); + + } + +} diff --git a/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportCategoryDto.java b/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportCategoryDto.java new file mode 100644 index 0000000..7504c2d --- /dev/null +++ b/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportCategoryDto.java @@ -0,0 +1,74 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2017 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  + * See the GNU Affero General Public License for more details. You should have received a copy of + * the GNU Affero General Public License along with this program. If not, see + * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.ao.reports.dto; + +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.validator.constraints.NotEmpty; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class EmbeddedReportCategoryDto implements EmbeddedReportCategory.Importer, + EmbeddedReportCategory.Exporter { + + private UUID id; + + @NotNull(message = "Name needs to be provided") + @NotEmpty(message = "Name cannot be empty") + private String name; + + /** + * Create new instance of EmbeddedReportCategoryDto based on given {@link EmbeddedReportCategory} + * + * @param embeddedReportCategory instance of Embedded Report Category + * @return new instance of EmbeddedReportCategoryDto. + */ + public static EmbeddedReportCategoryDto newInstance( + EmbeddedReportCategory embeddedReportCategory) { + if (embeddedReportCategory == null) { + return null; + } + + EmbeddedReportCategoryDto embeddedReportCategoryDto = new EmbeddedReportCategoryDto(); + embeddedReportCategory.export(embeddedReportCategoryDto); + + return embeddedReportCategoryDto; + } + + /** + * Create new list of EmbeddedReportCategoryDto based on given list + * of {@link EmbeddedReportCategory} + * + * @param embeddedReportCategories list of {@link EmbeddedReportCategory} + * @return new list of EmbeddedReportCategoryDto. + */ + public static List newInstance( + Iterable embeddedReportCategories) { + return StreamSupport.stream(embeddedReportCategories.spliterator(), false) + .map(EmbeddedReportCategoryDto::newInstance) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportDto.java b/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportDto.java index e18e5df..7cce4b3 100644 --- a/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportDto.java +++ b/src/main/java/org/openlmis/ao/reports/dto/EmbeddedReportDto.java @@ -28,6 +28,7 @@ import org.openlmis.ao.reports.domain.EmbeddedReport; import org.openlmis.ao.reports.domain.EmbeddedReport.Exporter; import org.openlmis.ao.reports.domain.EmbeddedReport.Importer; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; @Getter @Setter @@ -45,9 +46,9 @@ public class EmbeddedReportDto implements Importer, Exporter { @NotEmpty(message = "URL cannot be empty") private String url; - @NotNull(message = "Category needs to be provided") - @NotEmpty(message = "Category cannot be empty") - private String category; + private EmbeddedReportCategoryDto category; + + private boolean enabled; /** * Create new instance of EmbeddedReportDto based on given {@link EmbeddedReport} @@ -78,4 +79,9 @@ public static List newInstance(Iterable embed .collect(Collectors.toList()); } + @Override + public void setCategory(EmbeddedReportCategory category) { + this.category = new EmbeddedReportCategoryDto(); + category.export(this.category); + } } diff --git a/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportCategoryMessageKeys.java b/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportCategoryMessageKeys.java new file mode 100644 index 0000000..7b845e9 --- /dev/null +++ b/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportCategoryMessageKeys.java @@ -0,0 +1,11 @@ +package org.openlmis.ao.reports.i18n; + +public class EmbeddedReportCategoryMessageKeys extends ReportingMessageKeys { + + private static final String ERROR = join(SERVICE_ERROR, "embeddedReportCategory"); + + public static final String ERROR_EMBEDDED_REPORT_CATEGORY_NAME_DUPLICATED = + join(ERROR, "name", "duplicated"); + public static final String ERROR_EMBEDDED_REPORT_CATEGORY_NOT_FOUND = join(ERROR, NOT_FOUND); + +} diff --git a/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportsMessageKeys.java b/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportsMessageKeys.java index d7418c1..56b8281 100644 --- a/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportsMessageKeys.java +++ b/src/main/java/org/openlmis/ao/reports/i18n/EmbeddedReportsMessageKeys.java @@ -3,8 +3,11 @@ public class EmbeddedReportsMessageKeys extends ReportingMessageKeys { private static final String ERROR = join(SERVICE_ERROR, "embeddedReport"); + private static final String ID = "id"; + private static final String MISMATCH = "mismatch"; public static final String ERROR_EMBEDDED_REPORT_NAME_DUPLICATED = join(ERROR, "name", "duplicated"); public static final String ERROR_EMBEDDED_REPORT_NOT_FOUND = join(ERROR, NOT_FOUND); + public static final String ERROR_EMBEDDED_REPORT_ID_MISMATCH = join(ERROR, ID, MISMATCH); } diff --git a/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportCategoryRepository.java b/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportCategoryRepository.java new file mode 100644 index 0000000..b07e41c --- /dev/null +++ b/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportCategoryRepository.java @@ -0,0 +1,16 @@ +package org.openlmis.ao.reports.repository; + +import java.util.Optional; +import java.util.UUID; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; + +public interface EmbeddedReportCategoryRepository extends + PagingAndSortingRepository { + + EmbeddedReportCategory findByName(@Param("name") String name); + + Optional findById(UUID id); + +} diff --git a/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportRepository.java b/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportRepository.java index 4b1118a..ef05812 100644 --- a/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportRepository.java +++ b/src/main/java/org/openlmis/ao/reports/repository/EmbeddedReportRepository.java @@ -1,6 +1,7 @@ package org.openlmis.ao.reports.repository; import java.util.List; +import java.util.Optional; import java.util.UUID; import org.openlmis.ao.reports.domain.EmbeddedReport; import org.springframework.data.domain.Page; @@ -16,6 +17,8 @@ public interface EmbeddedReportRepository extends PagingAndSortingRepository findAll(Pageable pageable); - Page findAllByCategory(String category, Pageable pageable); + Page findAllByCategoryName(String name, Pageable pageable); + + Optional findById(UUID id); } \ No newline at end of file diff --git a/src/main/java/org/openlmis/ao/reports/service/PermissionService.java b/src/main/java/org/openlmis/ao/reports/service/PermissionService.java index 0f2e99b..51e59db 100644 --- a/src/main/java/org/openlmis/ao/reports/service/PermissionService.java +++ b/src/main/java/org/openlmis/ao/reports/service/PermissionService.java @@ -24,6 +24,7 @@ public class PermissionService { public static final String REPORT_TEMPLATES_EDIT = "REPORT_TEMPLATES_EDIT"; public static final String REPORTS_VIEW = "REPORTS_VIEW"; public static final String EMBEDDED_REPORTS_VIEW = "EMBEDDED_REPORTS_VIEW"; + public static final String EMBEDDED_REPORTS_CATEGORY_MANAGE = "EMBEDDED_REPORTS_CATEGORY_MANAGE"; public static final String ORDERS_VIEW = "ORDERS_VIEW"; public static final String USERS_MANAGE = "USERS_MANAGE"; public static final UUID ORDER_ID = @@ -80,6 +81,13 @@ public void canViewEmbeddedReports() { checkPermission(EMBEDDED_REPORTS_VIEW); } + /** + * Checks if current user has permission to view embedded reports. + */ + public void canViewEmbeddedReportsCategory() { + checkPermission(EMBEDDED_REPORTS_CATEGORY_MANAGE); + } + /** * Checks if current user has permission to view a requisition. */ diff --git a/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportCategoryController.java b/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportCategoryController.java new file mode 100644 index 0000000..bdf3f1b --- /dev/null +++ b/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportCategoryController.java @@ -0,0 +1,149 @@ +package org.openlmis.ao.reports.web; + +import static org.openlmis.ao.reports.i18n.EmbeddedReportCategoryMessageKeys.ERROR_EMBEDDED_REPORT_CATEGORY_NAME_DUPLICATED; +import static org.openlmis.ao.reports.i18n.EmbeddedReportCategoryMessageKeys.ERROR_EMBEDDED_REPORT_CATEGORY_NOT_FOUND; +import static org.openlmis.ao.reports.web.EmbeddedReportCategoryController.RESOURCE_PATH; + +import javax.validation.Valid; +import java.util.UUID; +import org.apache.log4j.Logger; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; +import org.openlmis.ao.reports.dto.EmbeddedReportCategoryDto; +import org.openlmis.ao.reports.exception.NotFoundMessageException; +import org.openlmis.ao.reports.exception.ValidationMessageException; +import org.openlmis.ao.reports.i18n.EmbeddedReportCategoryMessageKeys; +import org.openlmis.ao.reports.repository.EmbeddedReportCategoryRepository; +import org.openlmis.ao.reports.service.PermissionService; +import org.openlmis.ao.utils.Message; +import org.openlmis.ao.utils.Pagination; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +@Controller +@Transactional +@RequestMapping(RESOURCE_PATH) +public class EmbeddedReportCategoryController extends BaseController { + + public static final String RESOURCE_PATH = "/api/reports/embeddedReportCategories"; + + private static final Logger LOGGER = Logger.getLogger(EmbeddedReportCategoryController.class); + + @Autowired + private EmbeddedReportCategoryRepository embeddedReportCategoryRepository; + + @Autowired + private PermissionService permissionService; + + /** + * Get chosen embedded report category. + * + * @param categoryId UUID of embedded report category we want to get + * @return Embedded report. + */ + @GetMapping(value = "/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public EmbeddedReportCategoryDto getEmbeddedReportCategory(@PathVariable("id") UUID categoryId) { + permissionService.canViewEmbeddedReportsCategory(); + EmbeddedReportCategory embeddedReportCategory = embeddedReportCategoryRepository + .findOne(categoryId); + + if (embeddedReportCategory == null) { + throw new NotFoundMessageException( + EmbeddedReportCategoryMessageKeys.ERROR_EMBEDDED_REPORT_CATEGORY_NOT_FOUND); + } + + return EmbeddedReportCategoryDto.newInstance(embeddedReportCategory); + } + + /** + * Get page of all embedded report categories. + * + * @return All embedded report categories matching certain criteria. + */ + @GetMapping + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Page getAllEmbeddedReportCategories(Pageable pageable) { + permissionService.canViewEmbeddedReportsCategory(); + + Page embeddedReportCategories = + embeddedReportCategoryRepository.findAll(pageable); + + return Pagination.getPage(EmbeddedReportCategoryDto.newInstance(embeddedReportCategories), + pageable); + } + + /** + * Adds or updates embedded report category to database. + * + * @param dto Data transfer object containing Embedded Report Category data. + */ + @PostMapping + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public EmbeddedReportCategoryDto createEmbeddedReportCategory( + @Valid @RequestBody EmbeddedReportCategoryDto dto) { + permissionService.canViewEmbeddedReportsCategory(); + LOGGER.debug("Creating new embedded report category"); + + EmbeddedReportCategory embeddedReportCategoryToUpdate = + embeddedReportCategoryRepository.findByName(dto.getName()); + if (embeddedReportCategoryToUpdate == null) { + LOGGER.debug("Creating new embedded report category"); + embeddedReportCategoryToUpdate = EmbeddedReportCategory.newInstance(dto); + embeddedReportCategoryToUpdate.setId(null); + } else { + LOGGER.debug("Existing embedded report category found, updating"); + dto.setId(embeddedReportCategoryToUpdate.getId()); + embeddedReportCategoryToUpdate = EmbeddedReportCategory.newInstance(dto); + } + + try { + embeddedReportCategoryToUpdate = embeddedReportCategoryRepository + .save(embeddedReportCategoryToUpdate); + } catch (DataIntegrityViolationException integrityException) { + throw new ValidationMessageException(new Message( + ERROR_EMBEDDED_REPORT_CATEGORY_NAME_DUPLICATED), integrityException); + } + + LOGGER.debug("Saved embedded report category with id: " + + embeddedReportCategoryToUpdate.getId()); + return EmbeddedReportCategoryDto.newInstance(embeddedReportCategoryToUpdate); + } + + /** + * Allows deleting embedded report category. + * + * @param categoryId UUID of embedded report category we want to delete + */ + @DeleteMapping(value = "/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteEmbeddedReportCategory(@PathVariable("id") UUID categoryId) { + permissionService.canViewEmbeddedReportsCategory(); + LOGGER.debug("Deleting embedded report category"); + EmbeddedReportCategory embeddedReportCategory = + embeddedReportCategoryRepository.findOne(categoryId); + if (embeddedReportCategory == null) { + throw new NotFoundMessageException(new Message( + ERROR_EMBEDDED_REPORT_CATEGORY_NOT_FOUND, categoryId)); + } else { + embeddedReportCategoryRepository.delete(embeddedReportCategory); + LOGGER.debug("Deleted embedded report category with id: " + categoryId); + } + } + +} diff --git a/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportController.java b/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportController.java index cd4b93c..97d2890 100644 --- a/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportController.java +++ b/src/main/java/org/openlmis/ao/reports/web/EmbeddedReportController.java @@ -5,13 +5,18 @@ import static org.openlmis.ao.reports.web.EmbeddedReportController.RESOURCE_PATH; import javax.validation.Valid; +import java.util.Objects; +import java.util.Optional; import java.util.UUID; import org.apache.log4j.Logger; import org.openlmis.ao.reports.domain.EmbeddedReport; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; import org.openlmis.ao.reports.dto.EmbeddedReportDto; import org.openlmis.ao.reports.exception.NotFoundMessageException; import org.openlmis.ao.reports.exception.ValidationMessageException; +import org.openlmis.ao.reports.i18n.EmbeddedReportCategoryMessageKeys; import org.openlmis.ao.reports.i18n.EmbeddedReportsMessageKeys; +import org.openlmis.ao.reports.repository.EmbeddedReportCategoryRepository; import org.openlmis.ao.reports.repository.EmbeddedReportRepository; import org.openlmis.ao.reports.service.PermissionService; import org.openlmis.ao.utils.Message; @@ -27,13 +32,13 @@ 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; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; - @Controller @Transactional @RequestMapping(RESOURCE_PATH) @@ -46,6 +51,9 @@ public class EmbeddedReportController extends BaseController { @Autowired private EmbeddedReportRepository embeddedReportRepository; + @Autowired + private EmbeddedReportCategoryRepository embeddedReportCategoryRepository; + @Autowired private PermissionService permissionService; @@ -83,7 +91,7 @@ public Page getAllEmbeddedReports( permissionService.canViewEmbeddedReports(); Page embeddedReports = (category != null) - ? embeddedReportRepository.findAllByCategory(category, pageable) + ? embeddedReportRepository.findAllByCategoryName(category, pageable) : embeddedReportRepository.findAll(pageable); return Pagination.getPage(EmbeddedReportDto.newInstance(embeddedReports), pageable); @@ -104,12 +112,13 @@ public EmbeddedReportDto createEmbeddedReport(@Valid @RequestBody EmbeddedReport EmbeddedReport embeddedReportToUpdate = embeddedReportRepository.findByName(dto.getName()); if (embeddedReportToUpdate == null) { LOGGER.debug("Creating new embedded report"); - embeddedReportToUpdate = EmbeddedReport.newInstance(dto); + embeddedReportToUpdate = new EmbeddedReport(); + updateReport(dto, embeddedReportToUpdate); embeddedReportToUpdate.setId(null); } else { LOGGER.debug("Existing embedded report found, updating"); dto.setId(embeddedReportToUpdate.getId()); - embeddedReportToUpdate = EmbeddedReport.newInstance(dto); + updateReport(dto, embeddedReportToUpdate); } try { @@ -130,7 +139,7 @@ public EmbeddedReportDto createEmbeddedReport(@Valid @RequestBody EmbeddedReport */ @DeleteMapping(value = "/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteTemplate(@PathVariable("id") UUID reportId) { + public void deleteEmbeddedReport(@PathVariable("id") UUID reportId) { permissionService.canViewEmbeddedReports(); LOGGER.debug("Deleting embedded report"); EmbeddedReport embeddedReport = embeddedReportRepository.findOne(reportId); @@ -143,4 +152,52 @@ public void deleteTemplate(@PathVariable("id") UUID reportId) { } } + /** + * Allows updating embedded report. + * + * @param id UUID of embedded report we want to update + */ + @PutMapping(value = "/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public EmbeddedReportDto updateEmbeddedReport(@PathVariable("id") UUID id, + @Valid @RequestBody EmbeddedReportDto embeddedReportDto) { + permissionService.canViewEmbeddedReports(); + if (null != embeddedReportDto.getId() && !Objects.equals(embeddedReportDto.getId(), id)) { + throw new ValidationMessageException( + EmbeddedReportsMessageKeys.ERROR_EMBEDDED_REPORT_ID_MISMATCH); + } + + LOGGER.debug("Updating embedded report"); + EmbeddedReport embeddedReport; + Optional embeddedReportOptional = embeddedReportRepository.findById(id); + if (embeddedReportOptional.isPresent()) { + embeddedReport = embeddedReportOptional.get(); + updateReport(embeddedReportDto, embeddedReport); + } else { + throw new NotFoundMessageException(ERROR_EMBEDDED_REPORT_NOT_FOUND); + } + embeddedReportRepository.save(embeddedReport); + + return EmbeddedReportDto.newInstance(embeddedReport); + } + + private void updateReport(EmbeddedReportDto newReport, EmbeddedReport reportToUpdate) { + reportToUpdate.updateFrom(newReport); + if (newReport.getCategory() != null) { + EmbeddedReportCategory category = findCategory(newReport); + reportToUpdate.setCategory(category); + } else { + reportToUpdate.setCategory(null); + } + } + + private EmbeddedReportCategory findCategory(EmbeddedReportDto newReport) { + return embeddedReportCategoryRepository + .findById(newReport.getCategory().getId()) + .orElseThrow(() -> new NotFoundMessageException( + EmbeddedReportCategoryMessageKeys.ERROR_EMBEDDED_REPORT_CATEGORY_NOT_FOUND)); + } + + } diff --git a/src/main/resources/api-definition.yaml b/src/main/resources/api-definition.yaml index a8bbef0..9e3070a 100644 --- a/src/main/resources/api-definition.yaml +++ b/src/main/resources/api-definition.yaml @@ -19,6 +19,10 @@ schemas: - embeddedReportDtoPage: !include schemas/embeddedReportDtoPage.json + - embeddedReportCategoryDto: !include schemas/embeddedReportCategoryDto.json + + - embeddedReportCategoryDtoPage: !include schemas/embeddedReportCategoryDtoPage.json + - jasperTemplateDtoArray: | { "type": "array", @@ -362,6 +366,71 @@ resourceTypes: body: application/json: schema: localizedMessage + /embeddedReportCategories: + displayName: Embedded report categories + get: + is: [ secured, paginated ] + description: Get all embedded report categories matching certain criteria. + responses: + 200: + body: + application/json: + schema: embeddedReportCategoryDtoPage + 403: + body: + application/json: + schema: localizedMessage + post: + is: [ secured ] + description: Create or update embedded report category. + body: + application/json: + schema: embeddedReportCategoryDtoPage + responses: + 200: + body: + application/json: + schema: embeddedReportCategoryDto + 403: + body: + application/json: + schema: localizedMessage + /{id}: + uriParameters: + id: + displayName: id + type: string + required: true + repeat: false + get: + is: [ secured ] + description: Get chosen embedded report category. + responses: + 200: + body: + application/json: + schema: embeddedReportCategoryDto + 403: + body: + application/json: + schema: localizedMessage + 404: + body: + application/json: + schema: localizedMessage + delete: + is: [ secured ] + description: Delete chosen embedded report category. + responses: + 204: + 403: + body: + application/json: + schema: localizedMessage + 404: + body: + application/json: + schema: localizedMessage /embeddedReports: displayName: Embedded reports get: @@ -427,7 +496,21 @@ resourceTypes: body: application/json: schema: localizedMessage - + put: + is: [ secured ] + description: Update embedded report. + body: + application/json: + schema: embeddedReportDto + responses: + 200: + body: + application/json: + schema: embeddedReportDto + 403: + body: + application/json: + schema: localizedMessage /settings: displayName: Settings. /{key}: diff --git a/src/main/resources/db/migration/20240325233459088__add_enabled_column_to_embedded_reports.sql b/src/main/resources/db/migration/20240325233459088__add_enabled_column_to_embedded_reports.sql new file mode 100644 index 0000000..47b083f --- /dev/null +++ b/src/main/resources/db/migration/20240325233459088__add_enabled_column_to_embedded_reports.sql @@ -0,0 +1 @@ +ALTER TABLE reports.embedded_reports ADD COLUMN enabled boolean DEFAULT true; diff --git a/src/main/resources/db/migration/20240326122000414__add_manage_embedded_reports_category_permission.sql b/src/main/resources/db/migration/20240326122000414__add_manage_embedded_reports_category_permission.sql new file mode 100644 index 0000000..8bb43a1 --- /dev/null +++ b/src/main/resources/db/migration/20240326122000414__add_manage_embedded_reports_category_permission.sql @@ -0,0 +1,20 @@ +DO $$ + BEGIN + IF EXISTS + ( SELECT 1 + FROM information_schema.tables + WHERE table_schema = 'referencedata' + AND table_name = 'rights' + ) + THEN + BEGIN + INSERT INTO referencedata.rights (id, description, name, type) VALUES ('f470482e-6ff0-4a91-b37a-00125673d593', NULL, 'EMBEDDED_REPORTS_CATEGORY_MANAGE', 'GENERAL_ADMIN'); + END; + END IF; + END +$$; + +CREATE TABLE reports.embedded_report_categories ( + id UUID PRIMARY KEY NOT NULL, + name text UNIQUE NOT NULL +); \ No newline at end of file diff --git a/src/main/resources/db/migration/20240326213622984__add_embedded_reports_category_constraint.sql b/src/main/resources/db/migration/20240326213622984__add_embedded_reports_category_constraint.sql new file mode 100644 index 0000000..01af2ce --- /dev/null +++ b/src/main/resources/db/migration/20240326213622984__add_embedded_reports_category_constraint.sql @@ -0,0 +1,3 @@ +ALTER TABLE reports.embedded_reports DROP COLUMN category; +ALTER TABLE reports.embedded_reports ADD COLUMN categoryId UUID NOT NULL; +ALTER TABLE reports.embedded_reports ADD CONSTRAINT fk_embedded_reports_category FOREIGN KEY (categoryid) REFERENCES reports.embedded_report_categories(id); diff --git a/src/main/resources/db/migration/20240513132831955__remove_not_null_constraint_for_categoryId_column.sql b/src/main/resources/db/migration/20240513132831955__remove_not_null_constraint_for_categoryId_column.sql new file mode 100644 index 0000000..59feb91 --- /dev/null +++ b/src/main/resources/db/migration/20240513132831955__remove_not_null_constraint_for_categoryId_column.sql @@ -0,0 +1,4 @@ +ALTER TABLE reports.embedded_reports DROP CONSTRAINT fk_embedded_reports_category; +ALTER TABLE reports.embedded_reports DROP COLUMN categoryId; +ALTER TABLE reports.embedded_reports ADD COLUMN categoryId UUID; +ALTER TABLE reports.embedded_reports ADD CONSTRAINT fk_embedded_reports_category FOREIGN KEY (categoryid) REFERENCES reports.embedded_report_categories(id); diff --git a/src/main/resources/schemas/embeddedReportCategoryDto.json b/src/main/resources/schemas/embeddedReportCategoryDto.json new file mode 100644 index 0000000..ae6078c --- /dev/null +++ b/src/main/resources/schemas/embeddedReportCategoryDto.json @@ -0,0 +1,20 @@ +{ + "type": "object", + "$schema": "http://json-schema.org/draft-04/schema", + "title": "EmbeddedReportCategoryDto", + "description": "A single embedded report category", + "properties": { + "id": { + "type": "string", + "title": "id" + }, + "name": { + "type": "string", + "title": "name" + } + }, + "required": [ + "id", + "name" + ] +} diff --git a/src/main/resources/schemas/embeddedReportCategoryDtoPage.json b/src/main/resources/schemas/embeddedReportCategoryDtoPage.json new file mode 100644 index 0000000..6224f56 --- /dev/null +++ b/src/main/resources/schemas/embeddedReportCategoryDtoPage.json @@ -0,0 +1,25 @@ +{ + "type": "object", + "$schema": "http://json-schema.org/draft-04/schema", + "title": "Collection", + "description": "Paginated collection", + "properties": { + "content": { + "type": "array", + "items": { "type": "object", "$ref": "embeddedReportCategoryDto.json" } + }, + "totalPages": { "type": "integer", "title": "totalPages" }, + "totalElements": { "type": "integer", "title": "totalElements" }, + "size": { "type": "integer", "title": "size" }, + "number": { "type": "integer", "title": "number" }, + "numberOfElements": { "type": "integer", "title": "numberOfElements" }, + "last": { "type": "boolean", "title": "last" }, + "first": { "type": "boolean", "title": "first" }, + "sort?": { + "title": "sort", + "type": "array", + "items": { "type": "object" } + } + }, + "required": ["content" , "totalPages" , "totalElements", "size", "number" , "numberOfElements" , "first" , "last"] +} \ No newline at end of file diff --git a/src/main/resources/schemas/embeddedReportDto.json b/src/main/resources/schemas/embeddedReportDto.json index 746c270..4adf305 100755 --- a/src/main/resources/schemas/embeddedReportDto.json +++ b/src/main/resources/schemas/embeddedReportDto.json @@ -17,14 +17,8 @@ "title": "url" }, "category": { - "type": "string", - "title": "category" + "type": "object", + "$ref": "embeddedReportCategoryDto.json" } - }, - "required": [ - "id", - "name", - "url", - "category" - ] + } } diff --git a/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportCategoryTest.java b/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportCategoryTest.java new file mode 100644 index 0000000..3d11552 --- /dev/null +++ b/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportCategoryTest.java @@ -0,0 +1,34 @@ +package org.openlmis.ao.reports.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.openlmis.ao.reports.dto.EmbeddedReportCategoryDto; +import org.openlmis.ao.testutils.EmbeddedReportCategoryDataBuilder; + +public class EmbeddedReportCategoryTest { + + @Test + public void shouldCreateNewInstance() { + EmbeddedReportCategory embeddedReportCategory = + new EmbeddedReportCategoryDataBuilder().build(); + EmbeddedReportCategoryDto importer = + EmbeddedReportCategoryDto.newInstance(embeddedReportCategory); + + EmbeddedReportCategory newInstance = EmbeddedReportCategory.newInstance(importer); + + assertThat(importer.getName()).isEqualTo(newInstance.getName()); + } + + @Test + public void shouldExportData() { + EmbeddedReportCategory embeddedReportCategory = + new EmbeddedReportCategoryDataBuilder().build(); + EmbeddedReportCategoryDto dto = new EmbeddedReportCategoryDto(); + + embeddedReportCategory.export(dto); + + assertThat(dto.getName()).isEqualTo(embeddedReportCategory.getName()); + } + +} diff --git a/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportTest.java b/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportTest.java index a0592a0..a1b05f3 100644 --- a/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportTest.java +++ b/src/test/java/org/openlmis/ao/reports/domain/EmbeddedReportTest.java @@ -17,7 +17,8 @@ public void shouldCreateNewInstance() { assertThat(importer.getName()).isEqualTo(newInstance.getName()); assertThat(importer.getUrl()).isEqualTo(newInstance.getUrl()); - assertThat(importer.getCategory()).isEqualTo(newInstance.getCategory()); + assertThat(importer.getCategory().getId()).isEqualTo(newInstance.getCategory().getId()); + assertThat(importer.isEnabled()).isEqualTo(newInstance.isEnabled()); } @Test @@ -29,7 +30,8 @@ public void shouldExportData() { assertThat(dto.getName()).isEqualTo(embeddedReport.getName()); assertThat(dto.getUrl()).isEqualTo(embeddedReport.getUrl()); - assertThat(dto.getCategory()).isEqualTo(embeddedReport.getCategory()); + assertThat(dto.getCategory().getId()).isEqualTo(embeddedReport.getCategory().getId()); + assertThat(dto.isEnabled()).isEqualTo(embeddedReport.isEnabled()); } } diff --git a/src/test/java/org/openlmis/ao/testutils/EmbeddedReportCategoryDataBuilder.java b/src/test/java/org/openlmis/ao/testutils/EmbeddedReportCategoryDataBuilder.java new file mode 100644 index 0000000..29c4278 --- /dev/null +++ b/src/test/java/org/openlmis/ao/testutils/EmbeddedReportCategoryDataBuilder.java @@ -0,0 +1,37 @@ +package org.openlmis.ao.testutils; + +import java.util.UUID; +import org.apache.commons.lang.RandomStringUtils; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; + +public class EmbeddedReportCategoryDataBuilder { + + private final UUID id = UUID.randomUUID(); + private String name = RandomStringUtils.random(6); + + public EmbeddedReportCategoryDataBuilder withName(String name) { + this.name = name; + return this; + } + + /** + * Builds an instance of the {@link EmbeddedReportCategory} class with populated ID. + * + * @return the instance of {@link EmbeddedReportCategory} class + */ + public EmbeddedReportCategory build() { + EmbeddedReportCategory embeddedReportCategory = buildAsNew(); + embeddedReportCategory.setId(id); + return embeddedReportCategory; + } + + /** + * Build an instance of the {@link EmbeddedReportCategory} class without ID field populated. + * + * @return the instance of {@link EmbeddedReportCategory} class + */ + public EmbeddedReportCategory buildAsNew() { + return new EmbeddedReportCategory(name); + } + +} diff --git a/src/test/java/org/openlmis/ao/testutils/EmbeddedReportDataBuilder.java b/src/test/java/org/openlmis/ao/testutils/EmbeddedReportDataBuilder.java index e9a98b5..36656ec 100644 --- a/src/test/java/org/openlmis/ao/testutils/EmbeddedReportDataBuilder.java +++ b/src/test/java/org/openlmis/ao/testutils/EmbeddedReportDataBuilder.java @@ -3,13 +3,15 @@ import java.util.UUID; import org.apache.commons.lang.RandomStringUtils; import org.openlmis.ao.reports.domain.EmbeddedReport; +import org.openlmis.ao.reports.domain.EmbeddedReportCategory; public class EmbeddedReportDataBuilder { private final UUID id = UUID.randomUUID(); private String name = RandomStringUtils.random(6); private String url = "http://example.com"; - private String category = "default-category"; + private EmbeddedReportCategory category = new EmbeddedReportCategoryDataBuilder().buildAsNew(); + private boolean enabled = true; public EmbeddedReportDataBuilder withName(String name) { this.name = name; @@ -21,11 +23,16 @@ public EmbeddedReportDataBuilder withUrl(String url) { return this; } - public EmbeddedReportDataBuilder withCategory(String category) { + public EmbeddedReportDataBuilder withCategory(EmbeddedReportCategory category) { this.category = category; return this; } + public EmbeddedReportDataBuilder disabled() { + this.enabled = false; + return this; + } + /** * Builds an instance of the {@link EmbeddedReport} class with populated ID. * @@ -46,7 +53,8 @@ public EmbeddedReport buildAsNew() { return new EmbeddedReport( name, url, - category + category, + enabled ); }