Skip to content

Commit 72d45ba

Browse files
DaDudekDawid Dudek
andauthored
https://jira.fingo.info/browse/IJ-326 urlop wypocz. przysług. field is calculated wrongly (#210)
* https://jira.fingo.info/browse/IJ-326 urlop wypocz. przysług. field is calculated wrongly * https://jira.fingo.info/browse/IJ-326 urlop wypocz. przysług. field is calculated wrongly * https://jira.fingo.info/browse/IJ-326 urlop wypocz. przysług. field is calculated wrongly * https://jira.fingo.info/browse/IJ-326 urlop wypocz. przysług. field is calculated wrongly --------- Co-authored-by: Dawid Dudek <[email protected]>
1 parent db09cb9 commit 72d45ba

File tree

5 files changed

+237
-118
lines changed

5 files changed

+237
-118
lines changed

src/main/java/info/fingo/urlopia/history/HistoryLogFilterCreator.java

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,53 @@ public class HistoryLogFilterCreator {
1212
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(UrlopiaApplication.DATE_TIME_FORMAT);
1313
private static final String CREATED_FIELD_FILTER = "created";
1414
private static final String USER_ID_FIELD_FILTER = "user.id";
15-
private static final String EVENT_FILTER = "userDetailsChangeEvent";
15+
private static final String EVENT_FIELD_FILTER = "userDetailsChangeEvent";
16+
private static final String COUNT_NEXT_YEAR_FIELD_FILTER = "countForNextYear";
1617

1718

19+
public static Filter filterBy(LocalDate date,
20+
Long userId){
21+
var formattedStartOfDay = getFormattedDayStart(date);
22+
var formattedEndOfDay = getFormattedDayEnd(date);
23+
return Filter.newBuilder()
24+
.and(USER_ID_FIELD_FILTER, Operator.EQUAL, String.valueOf(userId))
25+
.and(CREATED_FIELD_FILTER, Operator.GREATER_OR_EQUAL, formattedStartOfDay)
26+
.and(CREATED_FIELD_FILTER, Operator.LESS_OR_EQUAL, formattedEndOfDay)
27+
.build();
28+
}
29+
30+
public static Filter filterBy(LocalDate startDate,
31+
LocalDate endDate,
32+
Long userId){
33+
var formattedStartOfDay = getFormattedDayStart(startDate);
34+
var formattedEndOfDay = getFormattedDayEnd(endDate);
35+
return Filter.newBuilder()
36+
.and(USER_ID_FIELD_FILTER, Operator.EQUAL, String.valueOf(userId))
37+
.and(CREATED_FIELD_FILTER, Operator.GREATER_OR_EQUAL, formattedStartOfDay)
38+
.and(CREATED_FIELD_FILTER, Operator.LESS_OR_EQUAL, formattedEndOfDay)
39+
.build();
40+
}
41+
42+
private static String getFormattedDayStart(LocalDate date){
43+
var startOfDay = LocalDateTime.of(date, LocalTime.MIN);
44+
var formatter = DateTimeFormatter.ofPattern(UrlopiaApplication.DATE_TIME_FORMAT);
45+
return formatter.format(startOfDay);
46+
}
47+
48+
private static String getFormattedDayEnd(LocalDate date){
49+
var endOfDay = LocalDateTime.of(date, LocalTime.MAX);
50+
var formatter = DateTimeFormatter.ofPattern(UrlopiaApplication.DATE_TIME_FORMAT);
51+
return formatter.format(endOfDay);
52+
}
53+
1854
public static Filter filterBy(UserDetailsChangeEvent changeEvent,
1955
YearMonth minYearMonth){
2056
var firstDayOfMonth = minYearMonth.atDay(1);
2157
var startOfFirstDay = LocalDateTime.of(firstDayOfMonth, LocalTime.MIN);
2258

2359
return Filter.newBuilder()
2460
.and(CREATED_FIELD_FILTER, Operator.GREATER_OR_EQUAL, DATE_FORMATTER.format(startOfFirstDay))
25-
.and(EVENT_FILTER, Operator.EQUAL, changeEvent.name())
61+
.and(EVENT_FIELD_FILTER, Operator.EQUAL, changeEvent.name())
2662
.build();
2763
}
2864

@@ -39,7 +75,7 @@ public static Filter filterBy(UserDetailsChangeEvent changeEvent,
3975
.and(USER_ID_FIELD_FILTER, Operator.EQUAL, String.valueOf(userId))
4076
.and(CREATED_FIELD_FILTER, Operator.GREATER_OR_EQUAL, DATE_FORMATTER.format(startOfFirstDay))
4177
.and(CREATED_FIELD_FILTER, Operator.LESS_OR_EQUAL, DATE_FORMATTER.format(endOfLastDay))
42-
.and(EVENT_FILTER, Operator.EQUAL, changeEvent.name())
78+
.and(EVENT_FIELD_FILTER, Operator.EQUAL, changeEvent.name())
4379
.build();
4480
}
4581

@@ -56,7 +92,24 @@ public static Filter filterBy(UserDetailsChangeEvent changeEvent,
5692
.and(USER_ID_FIELD_FILTER, Operator.EQUAL, String.valueOf(userId))
5793
.and(CREATED_FIELD_FILTER, Operator.GREATER_OR_EQUAL, DATE_FORMATTER.format(startOfFirstDay))
5894
.and(CREATED_FIELD_FILTER, Operator.LESS_OR_EQUAL, DATE_FORMATTER.format(endOfLastDay))
59-
.and(EVENT_FILTER, Operator.EQUAL, changeEvent.name())
95+
.and(EVENT_FIELD_FILTER, Operator.EQUAL, changeEvent.name())
96+
.build();
97+
}
98+
99+
public static Filter filterBy(Integer year,
100+
Long userId,
101+
Boolean countForNextYear){
102+
var firstDayOfYear = LocalDate.of(year, 1, 1);
103+
var formattedFirstDayOfYear = getFormattedDayStart(firstDayOfYear);
104+
105+
var lastDayOfMonth = LocalDate.of(year,12,31);
106+
var formattedLastDaysOfMonth = getFormattedDayEnd(lastDayOfMonth);
107+
108+
return Filter.newBuilder()
109+
.and(USER_ID_FIELD_FILTER, Operator.EQUAL, String.valueOf(userId))
110+
.and(CREATED_FIELD_FILTER, Operator.GREATER_OR_EQUAL, formattedFirstDayOfYear)
111+
.and(CREATED_FIELD_FILTER, Operator.LESS_OR_EQUAL, formattedLastDaysOfMonth)
112+
.and(COUNT_NEXT_YEAR_FIELD_FILTER, Operator.EQUAL, String.valueOf(countForNextYear))
60113
.build();
61114
}
62115
}

src/main/java/info/fingo/urlopia/history/HistoryLogService.java

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919

2020
import java.time.LocalDate;
2121
import java.time.LocalDateTime;
22-
import java.time.LocalTime;
2322
import java.time.YearMonth;
2423
import java.time.format.DateTimeFormatter;
24+
import java.util.ArrayList;
2525
import java.util.List;
2626
import java.util.Optional;
2727

@@ -51,19 +51,17 @@ public Page<HistoryLogExcerptProjection> get(Filter filter,
5151

5252
public List<HistoryLogExcerptProjection> get(LocalDate date,
5353
Long userId) {
54-
var startOfDay = LocalDateTime.of(date, LocalTime.MIN);
55-
var endOfDay = LocalDateTime.of(date, LocalTime.MAX);
56-
var formatter = DateTimeFormatter.ofPattern(UrlopiaApplication.DATE_TIME_FORMAT);
57-
var formattedStartOfDay = formatter.format(startOfDay);
58-
var formattedEndOfDay = formatter.format(endOfDay);
59-
var filter = Filter.newBuilder()
60-
.and("user.id", Operator.EQUAL, String.valueOf(userId))
61-
.and(CREATED_FILTER, Operator.GREATER_OR_EQUAL, formattedStartOfDay)
62-
.and(CREATED_FILTER, Operator.LESS_OR_EQUAL, formattedEndOfDay)
63-
.build();
54+
var filter = HistoryLogFilterCreator.filterBy(date, userId);
6455
return historyLogRepository.findAll(filter, HistoryLogExcerptProjection.class);
6556
}
6657

58+
public List<HistoryLog> get(LocalDate startDate,
59+
LocalDate endDate,
60+
Long userId) {
61+
var filter = HistoryLogFilterCreator.filterBy(startDate, endDate, userId);
62+
return historyLogRepository.findAll(filter);
63+
}
64+
6765
public List<HistoryLogExcerptProjection> get(Long userId,
6866
Integer year,
6967
Filter filter) {
@@ -104,6 +102,13 @@ public Page<HistoryLogExcerptProjection> get(Long userId,
104102
return get(filterWithRestrictions, pageable);
105103
}
106104

105+
private List<HistoryLog> getCountForNextYearLogs(Integer year,
106+
Long userId,
107+
Boolean countForNextYear){
108+
var filter = HistoryLogFilterCreator.filterBy(year, userId, countForNextYear);
109+
return historyLogRepository.findAll(filter);
110+
}
111+
107112

108113
public List<HistoryLog> getBy(YearMonth yearMonth,
109114
UserDetailsChangeEvent userDetailsChangeEvent){
@@ -227,6 +232,72 @@ public Float countRemainingHours(Long userId) {
227232
return historyLogRepository.sumHours(userId);
228233
}
229234

235+
public float countRemainingForCurrentYear(Long userId,
236+
Integer year){
237+
var currentYearLogs = getCountForNextYearLogs(year, userId, false);
238+
var fromLastYear = getCountForNextYearLogs(year-1, userId, true);
239+
var resultLogs = new ArrayList<HistoryLog>();
240+
resultLogs.addAll(currentYearLogs);
241+
resultLogs.addAll(fromLastYear);
242+
var hours = 0f;
243+
for (var log: resultLogs){
244+
var request = log.getRequest();
245+
if (request == null){
246+
hours += log.getHours();
247+
}
248+
}
249+
return hours + countRemainingFromPreviousYear(userId, year);
250+
}
251+
252+
private float countRemainingFromPreviousYear(Long userId,
253+
Integer year){
254+
var hours = 0f;
255+
var lastDayOfPrevYear = LocalDate.of(year-1, 12, 31);
256+
var firstDay = LocalDate.of(0, 1,1);
257+
var logs = get(firstDay, lastDayOfPrevYear, userId);
258+
for (var log: logs){
259+
var request = log.getRequest();
260+
if (request == null){
261+
hours += countForPrevYearFromLogWithoutRequest(log, year);
262+
}
263+
else if (request.isNormal()){
264+
hours += countForPrevYearFromRequest(log, request, year-1);
265+
}
266+
}
267+
return hours;
268+
}
269+
270+
private float countForPrevYearFromRequest(HistoryLog historyLog,
271+
Request request,
272+
Integer year){
273+
var lastDayOfYear = LocalDate.of(year, 12, 31);
274+
if (request.getEndDate().isBefore(lastDayOfYear)){
275+
return -1 * request.getWorkingHours();
276+
}//we need to handle "next year requests"
277+
else {
278+
var firstMonthOfRequest = request.getStartDate().getMonthValue();
279+
var hours = 0;
280+
for (int month=firstMonthOfRequest; month<=12; month++){
281+
hours += usedHoursFromMonthCalculator.countUsedHours(year, month, historyLog);
282+
}
283+
return -1 * hours;
284+
}
285+
}
286+
287+
private float countForPrevYearFromLogWithoutRequest(HistoryLog historyLog,
288+
Integer year){
289+
var logYear = historyLog.getCreated().getYear();
290+
var logIsFromPastYear = logYear < year;
291+
var logIsFromNextYear = logYear > year;
292+
if (logIsFromNextYear){
293+
return 0;
294+
}
295+
if (!historyLog.getCountForNextYear() || logIsFromPastYear){
296+
return historyLog.getHours();
297+
}
298+
return 0;
299+
}
300+
230301
public float countRemainingHoursForYear(Long userId,
231302
Integer year) {
232303
var hours = 0f;

src/main/java/info/fingo/urlopia/reports/evidence/params/resolver/EvidenceReportVacationLeaveParamsResolver.java

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,8 @@ private String resolveLabel(){
4040
}
4141

4242
private String resolveRemainingHoursAtYearStart() {
43-
var fromPreviousYear = countRemainingFromPreviousYear(year, user.getId());
44-
var fromCurrentYear = countFromCurrentYear(year, user.getId());
45-
var remainingHoursAtYearStart = fromPreviousYear + fromCurrentYear;
46-
return formatResolvedHours(remainingHoursAtYearStart);
47-
}
48-
49-
private float countFromCurrentYear(int year,
50-
long userId){
51-
return historyLogService
52-
.getFromYear(userId, year).stream()
53-
.filter(historyLog -> historyLog.getRequest() == null)
54-
.filter(historyLog -> !historyLog.getCountForNextYear())
55-
.map(HistoryLog::getHours)
56-
.filter(hours -> hours > 0)
57-
.reduce(Float::sum)
58-
.orElse(0f);
59-
}
60-
61-
private float countRemainingFromPreviousYear(int year,
62-
long userId){
63-
return historyLogService.countRemainingHoursForYear(userId, year - 1);
43+
var remainingHoursForYear = historyLogService.countRemainingForCurrentYear(user.getId(),year);
44+
return formatResolvedHours(remainingHoursForYear);
6445
}
6546

6647
private Map<String,String> resolveVacationLeaveUsedHours(){

src/test/groovy/info/fingo/urlopia/history/HistoryLogServiceSpec.groovy

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,96 @@ class HistoryLogServiceSpec extends Specification {
263263
1 * nextLog.setPrevHistoryLog(prevLog)
264264
}
265265

266+
def "countRemainingForCurrentYear WHEN only log without request should sum it"(){
267+
given:
268+
def log = Mock(HistoryLog){
269+
getHours() >> 100
270+
}
271+
def log2 = Mock(HistoryLog) {
272+
getHours() >> -20
273+
}
274+
historyLogRepository.findAll(_ as Filter) >>> [[log, log2], [], []]
275+
usedHoursFromMonthCalculator.countUsedHours(_ as Integer, _ as Integer, _ as HistoryLog) >> -20
276+
277+
when:
278+
def result = historyLogService.countRemainingForCurrentYear(1,1)
279+
280+
then:
281+
result == 80
282+
}
283+
284+
def "countRemainingForCurrentYear WHEN log with request SHOULD not be added"(){
285+
given:
286+
def log = Mock(HistoryLog){
287+
getHours() >> 100
288+
}
289+
def log2 = Mock(HistoryLog) {
290+
getHours() >> -20
291+
getRequest() >> Mock(Request)
292+
}
293+
historyLogRepository.findAll(_ as Filter) >>> [[log, log2], [], []]
294+
295+
when:
296+
def result = historyLogService.countRemainingForCurrentYear(1,1)
297+
298+
then:
299+
result == 100
300+
}
301+
302+
def "countRemainingForCurrentYear WHEN log without request from prev year but countedOnNext SHOULD be added"(){
303+
given:
304+
def log = Mock(HistoryLog){
305+
getHours() >> 100
306+
}
307+
def log2 = Mock(HistoryLog) {
308+
getHours() >> -20
309+
}
310+
historyLogRepository.findAll(_ as Filter) >>> [[log], [log2], []]
311+
312+
when:
313+
def result = historyLogService.countRemainingForCurrentYear(1,1)
314+
315+
then:
316+
result == 80
317+
}
318+
319+
320+
def "countRemainingForCurrentYear WHEN remaining from prev year SHOULD be added"(){
321+
given:
322+
def log = Mock(HistoryLog){
323+
getHours() >> 100
324+
}
325+
def log2 = Mock(HistoryLog) {
326+
getHours() >> -20
327+
getRequest() >> Mock(Request) {
328+
isNormal() >> true
329+
getEndDate() >> LocalDate.MAX
330+
getStartDate() >> LocalDate.of(2022,12,1)
331+
}
332+
}
333+
historyLogRepository.findAll(_ as Filter) >>> [[log], [], [log2]]
334+
usedHoursFromMonthCalculator.countUsedHours(_ as Integer, _ as Integer, _ as HistoryLog) >> 20
335+
336+
when:
337+
def result = historyLogService.countRemainingForCurrentYear(1,1)
338+
339+
then:
340+
result == 80
341+
}
342+
343+
344+
345+
def "countRemainingForCurrentYear WHEN no logs SHOULD return 0"(){
346+
given:
347+
historyLogRepository.findAll(_ as Filter) >> []
348+
349+
when:
350+
def result = historyLogService.countRemainingForCurrentYear(1,1)
351+
352+
then:
353+
result == 0
354+
}
355+
266356
def "delete WHEN event is missing SHOULD throw exception"(){
267357
given:
268358
def nextLog = Mock(HistoryLog)

0 commit comments

Comments
 (0)