|
|
|
|
@@ -3,7 +3,11 @@ package de.financer.service;
|
|
|
|
|
import de.financer.ResponseReason;
|
|
|
|
|
import de.financer.config.FinancerConfig;
|
|
|
|
|
import de.financer.dba.RecurringTransactionRepository;
|
|
|
|
|
import de.financer.model.*;
|
|
|
|
|
import de.financer.dto.RecurringTransactionDueInRangeResponseDto;
|
|
|
|
|
import de.financer.model.Account;
|
|
|
|
|
import de.financer.model.HolidayWeekendType;
|
|
|
|
|
import de.financer.model.IntervalType;
|
|
|
|
|
import de.financer.model.RecurringTransaction;
|
|
|
|
|
import org.apache.commons.collections4.IterableUtils;
|
|
|
|
|
import org.apache.commons.lang3.BooleanUtils;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
@@ -17,9 +21,12 @@ import org.springframework.transaction.annotation.Propagation;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.time.Period;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.time.format.DateTimeParseException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
@@ -144,8 +151,19 @@ public class RecurringTransactionService {
|
|
|
|
|
// If so the recurring transaction is due today
|
|
|
|
|
.anyMatch((d) -> d.equals(now));
|
|
|
|
|
final boolean weekend = this.ruleService.isWeekend(now);
|
|
|
|
|
boolean defer = false;
|
|
|
|
|
|
|
|
|
|
// If a recurring transaction has holiday weekend type SKIP and today is either a weekend day or a holiday that
|
|
|
|
|
// transaction cannot be due today
|
|
|
|
|
if (recurringTransaction.getHolidayWeekendType() == HolidayWeekendType.SKIP && (holiday || weekend)) {
|
|
|
|
|
LOGGER.debug(String
|
|
|
|
|
.format("Recurring transaction %s not due today because it has HWT %s and today is(holiday=%s or weekend=%s)",
|
|
|
|
|
ReflectionToStringBuilder.toString(recurringTransaction), recurringTransaction
|
|
|
|
|
.getHolidayWeekendType(), holiday, weekend));
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean defer = false;
|
|
|
|
|
|
|
|
|
|
if (holiday || weekend) {
|
|
|
|
|
defer = recurringTransaction.getHolidayWeekendType() == HolidayWeekendType.NEXT_WORKDAY
|
|
|
|
|
@@ -174,7 +192,7 @@ public class RecurringTransactionService {
|
|
|
|
|
* @return <code>true</code> if the recurring transaction is due today, <code>false</code> otherwise
|
|
|
|
|
*/
|
|
|
|
|
private boolean checkRecurringTransactionDuePast(RecurringTransaction recurringTransaction, LocalDate now) {
|
|
|
|
|
// Recurring transactions with holiday weekend type SAME_DAY or PREVIOUS_WORKDAY can't be due in the past
|
|
|
|
|
// Recurring transactions with holiday weekend type SAME_DAY, SKIP or PREVIOUS_WORKDAY can't be due in the past
|
|
|
|
|
if (!HolidayWeekendType.NEXT_WORKDAY.equals(recurringTransaction.getHolidayWeekendType())) {
|
|
|
|
|
LOGGER.debug(String.format("Recurring transaction %s has HWT %s and thus cannot be due in the past",
|
|
|
|
|
ReflectionToStringBuilder.toString(recurringTransaction),
|
|
|
|
|
@@ -255,7 +273,7 @@ public class RecurringTransactionService {
|
|
|
|
|
* @return <code>true</code> if the recurring transaction is due today, <code>false</code> otherwise
|
|
|
|
|
*/
|
|
|
|
|
private boolean checkRecurringTransactionDueFuture(RecurringTransaction recurringTransaction, LocalDate now) {
|
|
|
|
|
// Recurring transactions with holiday weekend type SAME_DAY or PREVIOUS_WORKDAY can't be due in the future
|
|
|
|
|
// Recurring transactions with holiday weekend type SAME_DAY, SKIP or PREVIOUS_WORKDAY can't be due in the future
|
|
|
|
|
if (!HolidayWeekendType.PREVIOUS_WORKDAY.equals(recurringTransaction.getHolidayWeekendType())) {
|
|
|
|
|
LOGGER.debug(String.format("Recurring transaction %s has HWT %s and thus cannot be due in the future",
|
|
|
|
|
ReflectionToStringBuilder.toString(recurringTransaction),
|
|
|
|
|
@@ -267,12 +285,12 @@ public class RecurringTransactionService {
|
|
|
|
|
// If today is a weekend day or holiday the recurring transaction cannot be due today, because the
|
|
|
|
|
// holiday weekend type says PREVIOUS_WORKDAY.
|
|
|
|
|
if (this.ruleService.isHoliday(now) || this.ruleService.isWeekend(now)) {
|
|
|
|
|
LOGGER.debug(String.format("Recurring transaction %s has HWT %s and today is either a holiday or weekend," +
|
|
|
|
|
" thus it cannot be due in the future",
|
|
|
|
|
ReflectionToStringBuilder.toString(recurringTransaction),
|
|
|
|
|
recurringTransaction.getHolidayWeekendType()));
|
|
|
|
|
LOGGER.debug(String.format("Recurring transaction %s has HWT %s and today is either a holiday or weekend," +
|
|
|
|
|
" thus it cannot be due in the future",
|
|
|
|
|
ReflectionToStringBuilder.toString(recurringTransaction),
|
|
|
|
|
recurringTransaction.getHolidayWeekendType()));
|
|
|
|
|
|
|
|
|
|
return false; // early return
|
|
|
|
|
return false; // early return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -313,7 +331,6 @@ public class RecurringTransactionService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Transactional(propagation = Propagation.REQUIRED)
|
|
|
|
|
public ResponseReason createRecurringTransaction(String fromAccountKey, String toAccountKey, Long amount,
|
|
|
|
|
String description, String holidayWeekendType,
|
|
|
|
|
@@ -512,4 +529,26 @@ public class RecurringTransactionService {
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This method calculates all {@link RecurringTransaction}s due in the given date range.
|
|
|
|
|
*
|
|
|
|
|
* @param start the start of the range, inclusive
|
|
|
|
|
* @param end the end of the range, inclusive
|
|
|
|
|
*
|
|
|
|
|
* @return a list of date->recurring transactions due mappings
|
|
|
|
|
*/
|
|
|
|
|
public Iterable<RecurringTransactionDueInRangeResponseDto> getAllDueInRange(String start, String end) {
|
|
|
|
|
final List<RecurringTransactionDueInRangeResponseDto> dueInRange = new ArrayList<>();
|
|
|
|
|
final LocalDate startDate = LocalDate
|
|
|
|
|
.parse(start, DateTimeFormatter.ofPattern(this.financerConfig.getDateFormat()));
|
|
|
|
|
final LocalDate tmpEndDate = LocalDate
|
|
|
|
|
.parse(end, DateTimeFormatter.ofPattern(this.financerConfig.getDateFormat()));
|
|
|
|
|
final LocalDate endDate = tmpEndDate.plusDays(1); // Range end is always exclusive in Java API
|
|
|
|
|
|
|
|
|
|
startDate.datesUntil(endDate, Period.ofDays(1)).forEach(d -> dueInRange
|
|
|
|
|
.add(new RecurringTransactionDueInRangeResponseDto(d, this.getAllDueToday(d))));
|
|
|
|
|
|
|
|
|
|
return dueInRange;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|