From 7b47c89dddbf02b32e9b43698a9c80dd3c65e3b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20G=C3=A4chter?= Date: Mon, 16 Oct 2023 14:35:13 +0200 Subject: [PATCH] update overview view for teams without objectives --- .../V1_0_0__current-db-schema-for-testing.sql | 57 +++++++++---------- .../migration/V2_1_0__createOverviewView.sql | 15 ++--- .../AlignmentPersistenceServiceIT.java | 2 +- .../KeyResultPersistenceServiceIT.java | 22 ++++--- .../OverviewPersistenceServiceIT.java | 47 +++++++++++++++ 5 files changed, 98 insertions(+), 45 deletions(-) create mode 100644 backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java diff --git a/backend/src/main/resources/db/h2-db/database-h2-schema/V1_0_0__current-db-schema-for-testing.sql b/backend/src/main/resources/db/h2-db/database-h2-schema/V1_0_0__current-db-schema-for-testing.sql index 3f4c324b2c..c7645d81be 100644 --- a/backend/src/main/resources/db/h2-db/database-h2-schema/V1_0_0__current-db-schema-for-testing.sql +++ b/backend/src/main/resources/db/h2-db/database-h2-schema/V1_0_0__current-db-schema-for-testing.sql @@ -111,36 +111,35 @@ create table if not exists key_result DROP VIEW IF EXISTS OVERVIEW; CREATE VIEW OVERVIEW AS -select t.id as "team_id", - t.name as "team_name", - coalesce(o.id, -1) as "objective_id", - o.title as "objective_title", - o.state as "objective_state", - q.id as "quarter_id", - q.label as "quarter_label", - coalesce(kr.id, -1) as "key_result_id", - kr.title as "key_result_title", - kr.key_result_type as "key_result_type", - kr.unit, - kr.baseline, - kr.stretch_goal, - kr.commit_zone, - kr.target_zone, - kr.stretch_zone, - coalesce(c.id, -1) as "check_in_id", - c.value_metric as "check_in_value", - c.zone as "check_in_zone", - c.confidence, - c.created_on -FROM TEAM T - LEFT JOIN OBJECTIVE O ON T.ID = O.TEAM_ID - LEFT JOIN QUARTER Q ON O.QUARTER_ID = Q.ID +SELECT TQ.TEAM_ID AS "TEAM_ID", + TQ.NAME AS "TEAM_NAME", + TQ.QUATER_ID AS "QUARTER_ID", + TQ.LABEL AS "QUARTER_LABEL", + COALESCE(O.ID, -1) AS "OBJECTIVE_ID", + O.TITLE AS "OBJECTIVE_TITLE", + O.STATE AS "OBJECTIVE_STATE", + COALESCE(KR.ID, -1) AS "KEY_RESULT_ID", + KR.TITLE AS "KEY_RESULT_TITLE", + KR.KEY_RESULT_TYPE AS "KEY_RESULT_TYPE", + KR.UNIT, + KR.BASELINE, + KR.STRETCH_GOAL, + KR.COMMIT_ZONE, + KR.TARGET_ZONE, + KR.STRETCH_ZONE, + COALESCE(C.ID, -1) AS "CHECK_IN_ID", + C.VALUE_METRIC AS "CHECK_IN_VALUE", + C.ZONE AS "CHECK_IN_ZONE", + C.CONFIDENCE, + C.CREATED_ON +FROM (SELECT T.ID AS TEAM_ID, T.NAME, Q.ID AS QUATER_ID, Q.LABEL + FROM TEAM T, + QUARTER Q) TQ + LEFT JOIN OBJECTIVE O ON TQ.TEAM_ID = O.TEAM_ID AND TQ.QUATER_ID = O.QUARTER_ID LEFT JOIN KEY_RESULT KR ON O.ID = KR.OBJECTIVE_ID - LEFT JOIN check_in C ON KR.ID = C.KEY_RESULT_ID AND C.modified_on = (SELECT MAX(CC.modified_on) - FROM check_in CC - WHERE CC.KEY_RESULT_ID = C.KEY_RESULT_ID) -; - + LEFT JOIN CHECK_IN C ON KR.ID = C.KEY_RESULT_ID AND C.MODIFIED_ON = (SELECT MAX(CC.MODIFIED_ON) + FROM CHECK_IN CC + WHERE CC.KEY_RESULT_ID = C.KEY_RESULT_ID); create table if not exists alignment ( id bigint not null, diff --git a/backend/src/main/resources/db/migration/V2_1_0__createOverviewView.sql b/backend/src/main/resources/db/migration/V2_1_0__createOverviewView.sql index 7e4d7d1e9f..11379b3943 100644 --- a/backend/src/main/resources/db/migration/V2_1_0__createOverviewView.sql +++ b/backend/src/main/resources/db/migration/V2_1_0__createOverviewView.sql @@ -1,12 +1,12 @@ DROP VIEW IF EXISTS OVERVIEW; CREATE VIEW OVERVIEW AS -SELECT t.id AS "team_id", - t.name AS "team_name", +SELECT tq.team_id AS "team_id", + tq.name AS "team_name", + tq.quater_id AS "quarter_id", + tq.label AS "quarter_label", coalesce(o.id, -1) AS "objective_id", o.title AS "objective_title", o.state AS "objective_state", - q.id AS "quarter_id", - q.label AS "quarter_label", coalesce(kr.id, -1) AS "key_result_id", kr.title AS "key_result_title", kr.key_result_type AS "key_result_type", @@ -21,9 +21,10 @@ SELECT t.id AS "team_id", c.zone AS "check_in_zone", c.confidence, c.created_on -FROM TEAM T - LEFT JOIN OBJECTIVE O ON T.ID = O.TEAM_ID - LEFT JOIN QUARTER Q ON O.QUARTER_ID = Q.ID +FROM (select t.id as team_id, t.name, q.id as quater_id, q.label + from team t, + quarter q) tq + LEFT JOIN OBJECTIVE O ON TQ.TEAM_ID = O.TEAM_ID AND TQ.QUATER_ID = O.QUARTER_ID LEFT JOIN KEY_RESULT KR ON O.ID = KR.OBJECTIVE_ID LEFT JOIN CHECK_IN C ON KR.ID = C.KEY_RESULT_ID AND C.MODIFIED_ON = (SELECT MAX(CC.MODIFIED_ON) FROM CHECK_IN CC diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java index cc88cc3065..1cb8aea391 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java @@ -42,7 +42,7 @@ void tearDown() { alignmentPersistenceService.deleteById(createdAlignment.getId()); } } catch (ResponseStatusException ex) { - // created key result already deleted + // created alignment already deleted } finally { createdAlignment = null; } diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java index b759498710..a684bf5332 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java @@ -104,13 +104,13 @@ void recreateEntity_ShouldUpdateKeyResultNoTypeChange() { createdKeyResult = keyResultPersistenceService.save(keyResult); createdKeyResult.setTitle(KEY_RESULT_UPDATED); - KeyResult updatedKeyResult = keyResultPersistenceService.recreateEntity(createdKeyResult.getId(), + KeyResult recreatedKeyResult = keyResultPersistenceService.recreateEntity(createdKeyResult.getId(), createdKeyResult); assertNotNull(createdKeyResult.getId()); - assertEquals(KEY_RESULT_UPDATED, updatedKeyResult.getTitle()); - assertEquals(createdKeyResult.getOwner().getId(), updatedKeyResult.getOwner().getId()); - assertEquals(createdKeyResult.getObjective().getId(), updatedKeyResult.getObjective().getId()); + assertEquals(KEY_RESULT_UPDATED, recreatedKeyResult.getTitle()); + assertEquals(createdKeyResult.getOwner().getId(), recreatedKeyResult.getOwner().getId()); + assertEquals(createdKeyResult.getObjective().getId(), recreatedKeyResult.getObjective().getId()); // Should delete the old KeyResult ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { @@ -118,6 +118,9 @@ void recreateEntity_ShouldUpdateKeyResultNoTypeChange() { }); assertEquals(HttpStatus.NOT_FOUND, exception.getStatus()); assertEquals("KeyResult with id " + createdKeyResult.getId() + " not found", exception.getReason()); + + // delete re-created key result in tearDown() + createdKeyResult = recreatedKeyResult; } @Test @@ -131,13 +134,13 @@ void recreateEntity_ShouldUpdateKeyResultWithTypeChange() { .withOwner(createdKeyResult.getOwner()).withCreatedBy(createdKeyResult.getCreatedBy()) .withCreatedOn(createdKeyResult.getCreatedOn()).build(); - KeyResult updatedKeyResult = keyResultPersistenceService.recreateEntity(keyResultOrdinal.getId(), + KeyResult recreatedKeyResult = keyResultPersistenceService.recreateEntity(keyResultOrdinal.getId(), keyResultOrdinal); assertNotNull(createdKeyResult.getId()); - assertEquals(createdKeyResult.getObjective().getId(), updatedKeyResult.getObjective().getId()); - assertEquals(KEY_RESULT_UPDATED, updatedKeyResult.getTitle()); - assertEquals(createdKeyResult.getOwner().getId(), updatedKeyResult.getOwner().getId()); + assertEquals(createdKeyResult.getObjective().getId(), recreatedKeyResult.getObjective().getId()); + assertEquals(KEY_RESULT_UPDATED, recreatedKeyResult.getTitle()); + assertEquals(createdKeyResult.getOwner().getId(), recreatedKeyResult.getOwner().getId()); // Should delete the old KeyResult ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { @@ -145,6 +148,9 @@ void recreateEntity_ShouldUpdateKeyResultWithTypeChange() { }); assertEquals(HttpStatus.NOT_FOUND, exception.getStatus()); assertEquals("KeyResult with id " + createdKeyResult.getId() + " not found", exception.getReason()); + + // delete re-created key result in tearDown() + createdKeyResult = recreatedKeyResult; } @Test diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java new file mode 100644 index 0000000000..686144bddf --- /dev/null +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java @@ -0,0 +1,47 @@ +package ch.puzzle.okr.service.persistence; + +import ch.puzzle.okr.models.overview.Overview; +import ch.puzzle.okr.models.overview.OverviewId; +import ch.puzzle.okr.test.SpringIntegrationTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringIntegrationTest +public class OverviewPersistenceServiceIT { + @Autowired + private OverviewPersistenceService overviewPersistenceService; + + @Test + void getOverviewByQuarterIdAndTeamIds_ShouldReturnOverviews() { + List overviews = overviewPersistenceService.getOverviewByQuarterIdAndTeamIds(2L, List.of(5L, 6L, 8L)); + + assertEquals(13, overviews.size()); + overviews.forEach(overview -> matchOverviewId(overview.getOverviewId())); + } + + private boolean matchOverviewId(OverviewId overviewId) { + return getExpectedOverviewIds().anyMatch(id -> id.equals(overviewId)); + } + + private static Stream getExpectedOverviewIds() { + return Stream.of(OverviewId.of(5L, 3L, 3L, 9L), // + OverviewId.of(5L, 3L, 3L, 9L), // + OverviewId.of(5L, 3L, 4L, 8L), // + OverviewId.of(5L, 3L, 5L, 7L), // + OverviewId.of(5L, 4L, 6L, 5L), // + OverviewId.of(5L, 4L, 7L, 4L), // + OverviewId.of(5L, 4L, 8L, 2L), // + OverviewId.of(6L, 8L, 18L, 20L), // + OverviewId.of(6L, 8L, 19L, 19L), // + OverviewId.of(6L, 9L, 15L, 18L), // + OverviewId.of(6L, 9L, 16L, 17L), // + OverviewId.of(6L, 9L, 17L, 16L), // + OverviewId.of(6L, 10L, -1L, -1L), // + OverviewId.of(8L, -1L, -1L, -1L)); + } +}