Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/958 fix h2 quarters and tests #979

Merged
merged 38 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
031f17f
#958: only 4 Quarters in h2: current + next Quarter, Backlog and "GJ …
clean-coder Jul 12, 2024
2674daf
#958: fix IT Tests für Anpassung der Quartale
clean-coder Jul 12, 2024
3c849ba
#958: fix Cypress Tests für Anpassung der Quartale
clean-coder Jul 12, 2024
fba7e8c
#958: quarter sql string generator
clean-coder Jul 16, 2024
41c3780
#958: cleanup QuarterSqlGeneratorTest
clean-coder Jul 22, 2024
1dd5317
#958: remove unused classes
clean-coder Jul 22, 2024
90d8e2f
#958: rename QuarterSqlGenerator.java to Quarters
clean-coder Jul 22, 2024
65ac130
#958: refactoring - GJ uses Quarters functionality
clean-coder Jul 22, 2024
b32a5cb
#958: refactoring - cleanup
clean-coder Jul 22, 2024
694ae71
#958: refactoring - currentQuarter() returns QuarterDataWithGJ
clean-coder Jul 22, 2024
4067dae
#958: refactoring - GJ has no external dependencies (expect now)
clean-coder Jul 22, 2024
b3b496a
#958: start implementing h2 Function class
clean-coder Jul 23, 2024
4da2ccc
#958: refactoring - remove quarterDigit from QuarterData
clean-coder Jul 23, 2024
088bf1d
#958: refactoring (in Quarters: year for constructor, now for current…
clean-coder Jul 23, 2024
a2aac1f
#958: refactoring - rename QuarterDataWithGJ to QuarterData
clean-coder Jul 23, 2024
3585a97
#958: refactoring - create package util.quarter.generate
clean-coder Jul 23, 2024
946319b
#958: refactoring - rename GJ to QuarterLabel
clean-coder Jul 23, 2024
06c86fc
#958: added test for QuarterFunction
clean-coder Jul 23, 2024
ba67637
#958: cleanup test
clean-coder Jul 23, 2024
d83db58
#958: refactoring - rename to currentQuarter()
clean-coder Jul 23, 2024
a22c629
#958: refactoring - throw exception if currentQuarter() founds no mat…
clean-coder Jul 23, 2024
8c01b55
#958: cleanup - improve test method names
clean-coder Jul 23, 2024
9ccf4a4
#958: additional test for boundary dates
clean-coder Jul 23, 2024
73e519b
#958: cleanup - make helper methods private
clean-coder Jul 23, 2024
26fb3be
#958: cleanup - remove "test" main method
clean-coder Jul 23, 2024
f70dc58
#958: h2 immer aktuelle Quarter generieren (via Java)
clean-coder Jul 23, 2024
a36e46d
#958: cleanup
clean-coder Jul 23, 2024
b0c02d4
#958: cleanup
clean-coder Jul 23, 2024
f768635
#958: cleanup QuarterData
clean-coder Jul 24, 2024
3160deb
#958: cleanup QuartersTest
clean-coder Jul 24, 2024
1d304dc
#958: refactor nowAndQuarterLabelsForFuture test
clean-coder Jul 24, 2024
c9dd82d
#958: cleanup QuartersTest
clean-coder Jul 24, 2024
f12e224
#958: cleanup QuarterFunction
clean-coder Jul 24, 2024
b90dda4
#958: cleanup QuarterLabel
clean-coder Jul 24, 2024
30450a0
#958: cleanup Quarters
clean-coder Jul 24, 2024
9e7b17a
#958: cleanup QuarterLabelTest
clean-coder Jul 24, 2024
06c9fd4
#958: cleanup QuartersTest
clean-coder Jul 24, 2024
58a95b4
#958: use quarter utils in test mode only
pizzi-cato Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ch.puzzle.okr.util.quarter.generate;

import org.springframework.context.annotation.Profile;

import java.time.LocalDate;

/**
* Quarter data for H2 database.</br>
* </br>
* This class is used for testing purposes only. Do NOT use this class in production mode.
*/
@Profile("integration-test")
public record QuarterData(String label, LocalDate startDate, LocalDate endDate) {

public String startDateAsIsoString() {
return isoFormat(startDate);
}

public String endDateAsIsoString() {
return isoFormat(endDate);
}

private String isoFormat(LocalDate date) {
int year = date.getYear();
String month = String.format("%02d", date.getMonthValue());
String day = String.format("%02d", date.getDayOfMonth());
return year + "-" + month + "-" + day;
}

@Override
public String toString() {
return "(" + "'" + label() + "', " + //
"'" + startDateAsIsoString() + "', " + //
"'" + endDateAsIsoString() + "'" + //
")";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package ch.puzzle.okr.util.quarter.generate;

import org.springframework.context.annotation.Profile;

import java.time.LocalDate;

/**
* Quarter label for H2 database.</br>
* </br>
* This class is used for testing purposes only. Do NOT use this class in production mode.
*/
@Profile("integration-test")
public class QuarterLabel {
private final LocalDate date;

public QuarterLabel(LocalDate date) {
this.date = date;
}

public String label() {
return "GJ " + //
formatYearAs2Digits(firstYearOfGeschaeftsJahr()) + "/" + //
formatYearAs2Digits(secondYearOfGeschaeftsJahr()) + "-Q" + //
getQuarterDigit();
}

private int getQuarterDigit() {
int month = date.getMonthValue();
if (month < 4)
return 3;
if (month < 7)
return 4;
if (month < 10)
return 1;
return 2;
}

private int firstYearOfGeschaeftsJahr() {
if (isNowInNewGeschaeftsJahr()) {
return date.getYear();
}
return date.getYear() - 1;
}

private boolean isNowInNewGeschaeftsJahr() {
LocalDate startNewGJ = startOfNewGeschaeftsJahr();
return date.equals(startNewGJ) || date.isAfter(startNewGJ);
}

private int secondYearOfGeschaeftsJahr() {
return firstYearOfGeschaeftsJahr() + 1;
}

private int formatYearAs2Digits(int year) {
return year % 1000;
}

private LocalDate startOfNewGeschaeftsJahr() {
return LocalDate.of(date.getYear(), 7, 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package ch.puzzle.okr.util.quarter.generate;

import org.springframework.context.annotation.Profile;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
* Static initialize quarters for H2 database.</br>
* </br>
* This class is used for testing purposes only. Do NOT use this class in production mode.
*/
@Profile("integration-test")
public class Quarters {
private record QuarterDateRange(LocalDate startDate, LocalDate endDate) {
}

private static final String Q1_START = "07-01";
private static final String Q1_END = "09-30";
private static final String Q2_START = "10-01";
private static final String Q2_END = "12-31";
private static final String Q3_START = "01-01";
private static final String Q3_END = "03-31";
private static final String Q4_START = "04-01";
private static final String Q4_END = "06-30";

private final List<QuarterDateRange> quarters = new ArrayList<>();

public Quarters(int year) {
createQuarters(year);
}

private void createQuarters(int year) {
quarters.add(createQuarter(year, Q1_START, Q1_END));
quarters.add(createQuarter(year, Q2_START, Q2_END));
quarters.add(createQuarter(year, Q3_START, Q3_END));
quarters.add(createQuarter(year, Q4_START, Q4_END));
}

private QuarterDateRange createQuarter(int year, String startMonthDay, String endMonthDay) {
LocalDate startDate = toDate(year, startMonthDay);
LocalDate endDate = toDate(year, endMonthDay);
return new QuarterDateRange(startDate, endDate);
}

private LocalDate toDate(int year, String monthDay) {
return LocalDate.parse(year + "-" + monthDay);
}

public QuarterData currentQuarter(LocalDate date) {
for (QuarterDateRange quarter : quarters) {
if (isDateInQuarter(date, quarter.startDate(), quarter.endDate())) {
String label = new QuarterLabel(date).label();
return new QuarterData(label, quarter.startDate(), quarter.endDate());
}
}
throw new RuntimeException("No current quarter found for " + date);
}

private boolean isDateInQuarter(LocalDate date, LocalDate start, LocalDate end) {
boolean isAfterStart = date.equals(start) || date.isAfter(start);
boolean isBeforeEnd = date.isBefore(end) || date.equals(end);
return isAfterStart && isBeforeEnd;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ch.puzzle.okr.util.quarter.generate.h2;

import ch.puzzle.okr.util.quarter.generate.QuarterData;
import ch.puzzle.okr.util.quarter.generate.Quarters;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;

/**
* Quarter functions for H2 database.</br>
* </br>
* This class is used for testing purposes only. Do NOT use this class in production mode.
*/
@Component
@Profile("integration-test")
public class QuarterFunction {
public static final int CURRENT_QUARTER_DB_ID = 2;
public static final int NEXT_QUARTER_DB_ID = 3;

private static final Map<Integer, QuarterData> QUARTERS = new HashMap<>();

public static void initQuarterData() {
LocalDate now = LocalDate.now();
registerCurrentQuarterForDate(now, CURRENT_QUARTER_DB_ID);

LocalDate in3Months = now.plusMonths(3);
registerCurrentQuarterForDate(in3Months, NEXT_QUARTER_DB_ID);
}

private static void registerCurrentQuarterForDate(LocalDate date, int dbId) {
Quarters quarters = new Quarters(date.getYear());
QuarterData currentQuarter = quarters.currentQuarter(date);
QUARTERS.put(dbId, currentQuarter);
}

public static String currentQuarterLabel() {
return QUARTERS.get(CURRENT_QUARTER_DB_ID).label();
}

public static String currentQuarterStartDate() {
return QUARTERS.get(CURRENT_QUARTER_DB_ID).startDateAsIsoString();
}

public static String currentQuarterEndDate() {
return QUARTERS.get(CURRENT_QUARTER_DB_ID).endDateAsIsoString();
}

public static String nextQuarterLabel() {
return QUARTERS.get(NEXT_QUARTER_DB_ID).label();
}

public static String nextQuarterStartDate() {
return QUARTERS.get(NEXT_QUARTER_DB_ID).startDateAsIsoString();
}

public static String nextQuarterEndDate() {
return QUARTERS.get(NEXT_QUARTER_DB_ID).endDateAsIsoString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ values (1, 1, '[email protected]', 'Paco', 'Eggimann', 'peggimann'),
(41, 1, '[email protected]', 'Paco', 'Egiman', 'paco'),
(51, 1, '[email protected]', 'Robin', 'Papierer', 'robin');

CREATE ALIAS INIT_QUARTER_DATA FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.initQuarterData';
CREATE ALIAS CURRENT_QUARTER_LABEL FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.currentQuarterLabel';
CREATE ALIAS CURRENT_QUARTER_START_DATE FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.currentQuarterStartDate';
CREATE ALIAS CURRENT_QUARTER_END_DATE FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.currentQuarterEndDate';
CREATE ALIAS NEXT_QUARTER_LABEL FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.nextQuarterLabel';
CREATE ALIAS NEXT_QUARTER_START_DATE FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.nextQuarterStartDate';
CREATE ALIAS NEXT_QUARTER_END_DATE FOR 'ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.nextQuarterEndDate';

call INIT_QUARTER_DATA();

insert into quarter (id, label, start_date, end_date)
values (1, 'GJ 22/23-Q4', '2023-04-01', '2023-06-30'),
(2, 'GJ 23/24-Q1', '2023-07-01', '2023-09-30'),
(3, 'GJ 22/23-Q3', '2023-01-01', '2023-03-31'),
(4, 'GJ 22/23-Q2', '2022-10-01', '2022-12-31'),
(5, 'GJ 22/23-Q1', '2022-07-01', '2022-09-30'),
(6, 'GJ 21/22-Q4', '2022-04-01', '2022-06-30'),
(7, 'GJ 23/24-Q2', '2023-10-01', '2023-12-31'),
(8, 'GJ 23/24-Q3', '2024-01-01', '2024-03-31'),
(9, 'GJ 24/25-Q1', '2024-07-01', '2024-09-30'),
(199, 'Backlog', null, null);
values (2, CURRENT_QUARTER_LABEL(), CURRENT_QUARTER_START_DATE(), CURRENT_QUARTER_END_DATE()),
(3, NEXT_QUARTER_LABEL(), NEXT_QUARTER_START_DATE(), NEXT_QUARTER_END_DATE()),
(99, 'GJ ForTests', '2000-07-01', '2000-09-30'),
(999, 'Backlog', null, null);

insert into team (id, version, name)
values (4, 1, '/BBT'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ObjectivePersistenceServiceIT {
private static final String MODEL_WITH_ID_NOT_FOUND = "MODEL_WITH_ID_NOT_FOUND";
private static final String OBJECTIVE = "Objective";
private static final String ATTRIBUTE_NULL = "ATTRIBUTE_NULL";
private static final long GJ_FOR_TESTS_QUARTER_ID = 99L;
private final AuthorizationUser authorizationUser = defaultAuthorizationUser();
private Objective createdObjective;

Expand All @@ -46,9 +47,9 @@ private static Objective createObjective(Long id, int version) {
return Objective.Builder.builder().withId(id).withVersion(version).withTitle("title")
.withCreatedBy(User.Builder.builder().withId(1L).build())
.withTeam(Team.Builder.builder().withId(5L).build())
.withQuarter(Quarter.Builder.builder().withId(1L).build()).withDescription("This is our description")
.withState(State.DRAFT).withCreatedOn(LocalDateTime.MAX).withModifiedOn(LocalDateTime.MAX)
.withModifiedBy(User.Builder.builder().withId(1L).build()).build();
.withQuarter(Quarter.Builder.builder().withId(GJ_FOR_TESTS_QUARTER_ID).build())
.withDescription("This is our description").withState(State.DRAFT).withCreatedOn(LocalDateTime.MAX)
.withModifiedOn(LocalDateTime.MAX).withModifiedBy(User.Builder.builder().withId(1L).build()).build();
}

@AfterEach
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package ch.puzzle.okr.service.persistence;

import ch.puzzle.okr.test.TestHelper;
import ch.puzzle.okr.dto.ErrorDto;
import ch.puzzle.okr.exception.OkrResponseStatusException;
import ch.puzzle.okr.models.Quarter;
import ch.puzzle.okr.test.SpringIntegrationTest;
import ch.puzzle.okr.util.QuarterRangeChecker;
import ch.puzzle.okr.test.TestHelper;
import ch.puzzle.okr.util.quarter.check.QuarterRangeChecker;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -26,12 +26,12 @@ class QuarterPersistenceServiceIT {

@Test
void shouldReturnSingleQuarterWhenFindingByValidId() {
Quarter returnedQuarter = quarterPersistenceService.findById(1L);
Quarter returnedQuarter = quarterPersistenceService.findById(99L);

assertEquals(1L, returnedQuarter.getId());
assertEquals("GJ 22/23-Q4", returnedQuarter.getLabel());
assertEquals(LocalDate.of(2023, 4, 1), returnedQuarter.getStartDate());
assertEquals(LocalDate.of(2023, 6, 30), returnedQuarter.getEndDate());
assertEquals(99L, returnedQuarter.getId());
assertEquals("GJ ForTests", returnedQuarter.getLabel());
assertEquals(LocalDate.of(2000, 7, 1), returnedQuarter.getStartDate());
assertEquals(LocalDate.of(2000, 9, 30), returnedQuarter.getEndDate());
}

@Test
Expand All @@ -58,13 +58,26 @@ void shouldThrowExceptionWhenFindingQuarterWithIdNull() {
assertTrue(TestHelper.getAllErrorKeys(expectedErrors).contains(exception.getReason()));
}

@DisplayName("getMostCurrentQuarters() should return current quarter and future quarter and GJForTests quarter")
@Test
void shouldReturnCurrentQuarterFutureQuarterAnd4PastQuarters() {
void getMostCurrentQuartersShouldReturnCurrentQuarterAndFutureQuarterAndGJForTestsQuarter() {
List<Quarter> quarterListFromFunction = quarterPersistenceService.getMostCurrentQuarters();

assertEquals(6, quarterListFromFunction.size());
assertTrue(
quarterListFromFunction.get(0).getStartDate().isAfter(quarterListFromFunction.get(5).getStartDate()));
assertEquals(3, quarterListFromFunction.size());
assertGJForTestsQuarterIsFoundOnce(quarterListFromFunction);
assertCurrentQuarterIsFoundOnce(quarterListFromFunction);
}

private void assertGJForTestsQuarterIsFoundOnce(List<Quarter> quarters) {
long foundGJForTestsQuartersCount = quarters.stream()
.filter(quarter -> quarter.getLabel().equals("GJ ForTests")).count();
assertEquals(1, foundGJForTestsQuartersCount);
}

private void assertCurrentQuarterIsFoundOnce(List<Quarter> quarters) {
long foundCurrentQuartersCount = quarters.stream()
.filter(quarter -> QuarterRangeChecker.nowIsInQuarter(LocalDate.now(), quarter)).count();
assertEquals(1, foundCurrentQuartersCount);
}

@Test
Expand All @@ -80,13 +93,13 @@ void shouldReturnCurrentQuarter() {
@Test
void findByLabelShouldReturnSingleQuarterWhenLabelIsValid() {
// arrange + act
Quarter returnedQuarter = quarterPersistenceService.findByLabel("GJ 22/23-Q4");
Quarter returnedQuarter = quarterPersistenceService.findByLabel("GJ ForTests");

// assert
assertEquals(1L, returnedQuarter.getId());
assertEquals("GJ 22/23-Q4", returnedQuarter.getLabel());
assertEquals(LocalDate.of(2023, 4, 1), returnedQuarter.getStartDate());
assertEquals(LocalDate.of(2023, 6, 30), returnedQuarter.getEndDate());
assertEquals(99L, returnedQuarter.getId());
assertEquals("GJ ForTests", returnedQuarter.getLabel());
assertEquals(LocalDate.of(2000, 7, 1), returnedQuarter.getStartDate());
assertEquals(LocalDate.of(2000, 9, 30), returnedQuarter.getEndDate());
}

@DisplayName("findByLabel() should return null when label is not valid")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.puzzle.okr.util;
package ch.puzzle.okr.util.quarter.check;

import ch.puzzle.okr.models.Quarter;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.puzzle.okr.util;
package ch.puzzle.okr.util.quarter.check;

import ch.puzzle.okr.models.Quarter;
import org.junit.jupiter.api.DisplayName;
Expand Down
Loading
Loading