Add flag to control whether to remind about maturity of rec. transaction
This commit is contained in:
@@ -53,7 +53,7 @@ public class RecurringTransactionController {
|
||||
public ResponseEntity createRecurringTransaction(String fromAccountKey, String toAccountKey, Long amount,
|
||||
String description, String holidayWeekendType,
|
||||
String intervalType, String firstOccurrence,
|
||||
String lastOccurrence
|
||||
String lastOccurrence, Boolean remind
|
||||
) {
|
||||
final String decodedFrom = ControllerUtil.urlDecode(fromAccountKey);
|
||||
final String decodedTo = ControllerUtil.urlDecode(toAccountKey);
|
||||
@@ -62,13 +62,13 @@ public class RecurringTransactionController {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String
|
||||
.format("/recurringTransactions/createRecurringTransaction got parameters: %s, %s, %s, %s, %s, " +
|
||||
"%s, %s, %s", decodedFrom, decodedTo, amount, decodedDesc, holidayWeekendType,
|
||||
intervalType, firstOccurrence, lastOccurrence));
|
||||
"%s, %s, %s, %s", decodedFrom, decodedTo, amount, decodedDesc, holidayWeekendType,
|
||||
intervalType, firstOccurrence, lastOccurrence, remind));
|
||||
}
|
||||
|
||||
final ResponseReason responseReason = this.recurringTransactionService
|
||||
.createRecurringTransaction(decodedFrom, decodedTo, amount, decodedDesc, holidayWeekendType,
|
||||
intervalType, firstOccurrence, lastOccurrence);
|
||||
intervalType, firstOccurrence, lastOccurrence, remind);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String
|
||||
|
||||
@@ -21,6 +21,7 @@ public class RecurringTransaction {
|
||||
@Enumerated(EnumType.STRING)
|
||||
private HolidayWeekendType holidayWeekendType;
|
||||
private boolean deleted;
|
||||
private boolean remind;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
@@ -97,4 +98,12 @@ public class RecurringTransaction {
|
||||
public void setDeleted(boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public boolean isRemind() {
|
||||
return remind;
|
||||
}
|
||||
|
||||
public void setRemind(boolean remind) {
|
||||
this.remind = remind;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ 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;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.slf4j.Logger;
|
||||
@@ -261,16 +262,18 @@ public class RecurringTransactionService {
|
||||
return due;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public ResponseReason createRecurringTransaction(String fromAccountKey, String toAccountKey, Long amount,
|
||||
String description, String holidayWeekendType,
|
||||
String intervalType, String firstOccurrence,
|
||||
String lastOccurrence
|
||||
String lastOccurrence, Boolean remind
|
||||
) {
|
||||
final Account fromAccount = this.accountService.getAccountByKey(fromAccountKey);
|
||||
final Account toAccount = this.accountService.getAccountByKey(toAccountKey);
|
||||
ResponseReason response = validateParameters(fromAccount, toAccount, amount, holidayWeekendType, intervalType,
|
||||
firstOccurrence, lastOccurrence);
|
||||
firstOccurrence, lastOccurrence); // no validation of 'remind' as it's completely optional
|
||||
|
||||
// If we detected an issue with the given parameters return the first error found to the caller
|
||||
if (response != null) {
|
||||
@@ -279,7 +282,7 @@ public class RecurringTransactionService {
|
||||
|
||||
try {
|
||||
final RecurringTransaction transaction = buildRecurringTransaction(fromAccount, toAccount, amount,
|
||||
description, holidayWeekendType, intervalType, firstOccurrence, lastOccurrence);
|
||||
description, holidayWeekendType, intervalType, firstOccurrence, lastOccurrence, remind);
|
||||
|
||||
this.recurringTransactionRepository.save(transaction);
|
||||
|
||||
@@ -303,13 +306,14 @@ public class RecurringTransactionService {
|
||||
* @param intervalType the interval type
|
||||
* @param firstOccurrence the first occurrence
|
||||
* @param lastOccurrence the last occurrence, may be <code>null</code>
|
||||
* @param remind the remind flag
|
||||
*
|
||||
* @return the build {@link RecurringTransaction} instance
|
||||
*/
|
||||
private RecurringTransaction buildRecurringTransaction(Account fromAccount, Account toAccount, Long amount,
|
||||
String description, String holidayWeekendType,
|
||||
String intervalType, String firstOccurrence,
|
||||
String lastOccurrence
|
||||
String lastOccurrence, Boolean remind
|
||||
) {
|
||||
final RecurringTransaction recurringTransaction = new RecurringTransaction();
|
||||
|
||||
@@ -321,6 +325,9 @@ public class RecurringTransactionService {
|
||||
recurringTransaction.setIntervalType(IntervalType.valueOf(intervalType));
|
||||
recurringTransaction.setFirstOccurrence(LocalDate
|
||||
.parse(firstOccurrence, DateTimeFormatter.ofPattern(this.financerConfig.getDateFormat())));
|
||||
// See 'resources/database/postgres/readme_V1_0_0__init.txt'
|
||||
recurringTransaction.setDeleted(false);
|
||||
recurringTransaction.setRemind(BooleanUtils.toBooleanDefaultIfNull(remind, true));
|
||||
|
||||
// lastOccurrence is optional
|
||||
if (StringUtils.isNotEmpty(lastOccurrence)) {
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class SendRecurringTransactionReminderTask {
|
||||
|
||||
@@ -33,7 +35,7 @@ public class SendRecurringTransactionReminderTask {
|
||||
LOGGER.debug("Enter recurring transaction reminder task");
|
||||
}
|
||||
|
||||
final Iterable<RecurringTransaction> recurringTransactions = this.recurringTransactionService.getAllDueToday();
|
||||
Iterable<RecurringTransaction> recurringTransactions = this.recurringTransactionService.getAllDueToday();
|
||||
|
||||
// If no recurring transaction is due today we don't need to send a reminder
|
||||
if (IterableUtils.isEmpty(recurringTransactions)) {
|
||||
@@ -42,6 +44,12 @@ public class SendRecurringTransactionReminderTask {
|
||||
return; // early return
|
||||
}
|
||||
|
||||
// TODO Filtering currently happens in memory but should be done via SQL
|
||||
recurringTransactions = IterableUtils.toList(recurringTransactions)
|
||||
.stream()
|
||||
.filter((rt) -> rt.isRemind())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
LOGGER.info(String
|
||||
.format("%s recurring transaction are due today and are about to be included in the reminder email",
|
||||
IterableUtils.size(recurringTransactions)));
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Add a new column to the recurring transaction table that controls whether
|
||||
-- a reminder about the maturity should be send
|
||||
ALTER TABLE recurring_transaction
|
||||
ADD COLUMN remind BOOLEAN DEFAULT TRUE NOT NULL;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Add a new column to the recurring transaction table that controls whether
|
||||
-- a reminder about the maturity should be send
|
||||
ALTER TABLE recurring_transaction
|
||||
ADD COLUMN remind BOOLEAN DEFAULT 'TRUE' NOT NULL
|
||||
25
src/main/resources/database/postgres/readme_V1_0_0__init.txt
Normal file
25
src/main/resources/database/postgres/readme_V1_0_0__init.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
The recurring transaction table is defined like this (at least for postgres):
|
||||
-- Recurring transaction table
|
||||
CREATE TABLE recurring_transaction (
|
||||
id BIGINT NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
from_account_id BIGINT NOT NULL,
|
||||
to_account_id BIGINT NOT NULL,
|
||||
description VARCHAR(1000),
|
||||
amount BIGINT NOT NULL,
|
||||
interval_type VARCHAR(255) NOT NULL,
|
||||
first_occurrence DATE NOT NULL,
|
||||
last_occurrence DATE,
|
||||
holiday_weekend_type VARCHAR(255) NOT NULL,
|
||||
deleted BOOLEAN DEFAULT 'TRUE' NOT NULL,
|
||||
|
||||
CONSTRAINT fk_recurring_transaction_from_account FOREIGN KEY (from_account_id) REFERENCES account (id),
|
||||
CONSTRAINT fk_recurring_transaction_to_account FOREIGN KEY (to_account_id) REFERENCES account (id)
|
||||
);
|
||||
|
||||
Note the
|
||||
deleted BOOLEAN DEFAULT 'TRUE' NOT NULL,
|
||||
column definition. Not sure why the default is TRUE here is it doesn't make sense.
|
||||
It was probably a mistake, however fixing it here _WILL_ break existing installations
|
||||
as Flyway uses a checksum for scripts. So there is no easy fix, except for effectively
|
||||
overwriting this default in Java code when creating a new recurring transaction.
|
||||
See RecurringTransactionService.createRecurringTransaction()
|
||||
@@ -42,7 +42,8 @@ public class RecurringTransactionService_createRecurringTransactionIntegrationTe
|
||||
.param("description", "Monthly rent")
|
||||
.param("holidayWeekendType", "SAME_DAY")
|
||||
.param("intervalType", "MONTHLY")
|
||||
.param("firstOccurrence", "07.03.2019"))
|
||||
.param("firstOccurrence", "07.03.2019")
|
||||
.param("remind", "true"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.FROM_AND_TO_ACCOUNT_NOT_FOUND, response);
|
||||
@@ -70,7 +71,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.TO_ACCOUNT_NOT_FOUND, response);
|
||||
@@ -89,7 +91,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.FROM_ACCOUNT_NOT_FOUND, response);
|
||||
@@ -109,7 +112,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.INVALID_BOOKING_ACCOUNTS, response);
|
||||
@@ -129,7 +133,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.MISSING_AMOUNT, response);
|
||||
@@ -149,7 +154,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.AMOUNT_ZERO, response);
|
||||
@@ -169,7 +175,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
null,
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.MISSING_HOLIDAY_WEEKEND_TYPE, response);
|
||||
@@ -189,7 +196,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
"HOLIDAY_WEEKEND_TYPE",
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.INVALID_HOLIDAY_WEEKEND_TYPE, response);
|
||||
@@ -209,7 +217,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
null,
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.MISSING_INTERVAL_TYPE, response);
|
||||
@@ -229,7 +238,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
"INTERVAL_TYPE",
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.INVALID_INTERVAL_TYPE, response);
|
||||
@@ -249,7 +259,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
IntervalType.DAILY.name(),
|
||||
null,
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.MISSING_FIRST_OCCURRENCE, response);
|
||||
@@ -269,7 +280,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
IntervalType.DAILY.name(),
|
||||
"FIRST_OCCURRENCE",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.INVALID_FIRST_OCCURRENCE_FORMAT, response);
|
||||
@@ -289,7 +301,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
IntervalType.DAILY.name(),
|
||||
"07.03.2019",
|
||||
"LAST_OCCURRENCE");
|
||||
"LAST_OCCURRENCE",
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.INVALID_LAST_OCCURRENCE_FORMAT, response);
|
||||
@@ -310,7 +323,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
IntervalType.DAILY.name(),
|
||||
"07.03.2019",
|
||||
null);
|
||||
null,
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
|
||||
@@ -330,7 +344,8 @@ public class RecurringTransactionService_createRecurringTransactionTest {
|
||||
HolidayWeekendType.SAME_DAY.name(),
|
||||
IntervalType.DAILY.name(),
|
||||
"07.03.2019",
|
||||
null);
|
||||
null,
|
||||
Boolean.TRUE);
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(ResponseReason.OK, response);
|
||||
|
||||
@@ -36,9 +36,10 @@ public class SendRecurringTransactionReminderTaskTest {
|
||||
public void test_sendReminder() {
|
||||
// Arrange
|
||||
final Collection<RecurringTransaction> recurringTransactions = Arrays.asList(
|
||||
createRecurringTransaction("Test booking 1", "Income", "accounts.bank", Long.valueOf(250000)),
|
||||
createRecurringTransaction("Test booking 2", "Bank", "accounts.rent", Long.valueOf(41500)),
|
||||
createRecurringTransaction("Test booking 3", "Bank", "accounts.cash", Long.valueOf(5000))
|
||||
createRecurringTransaction("Test booking 1", "Income", "accounts.bank", Long.valueOf(250000), true),
|
||||
createRecurringTransaction("Test booking 2", "Bank", "accounts.rent", Long.valueOf(41500), true),
|
||||
createRecurringTransaction("Test booking 3", "Bank", "accounts.cash", Long.valueOf(5000), true),
|
||||
createRecurringTransaction("Test booking 4", "Car", "accounts.car", Long.valueOf(1234), false)
|
||||
);
|
||||
|
||||
Mockito.when(this.recurringTransactionService.getAllDueToday()).thenReturn(recurringTransactions);
|
||||
@@ -51,13 +52,14 @@ public class SendRecurringTransactionReminderTaskTest {
|
||||
Mockito.verify(this.mailSender, Mockito.times(1)).send(Mockito.any(SimpleMailMessage.class));
|
||||
}
|
||||
|
||||
private RecurringTransaction createRecurringTransaction(String description, String fromAccountKey, String toAccountKey, Long amount) {
|
||||
private RecurringTransaction createRecurringTransaction(String description, String fromAccountKey, String toAccountKey, Long amount, boolean remind) {
|
||||
final RecurringTransaction recurringTransaction = new RecurringTransaction();
|
||||
|
||||
recurringTransaction.setDescription(description);
|
||||
recurringTransaction.setFromAccount(createAccount(fromAccountKey));
|
||||
recurringTransaction.setToAccount(createAccount(toAccountKey));
|
||||
recurringTransaction.setAmount(amount);
|
||||
recurringTransaction.setRemind(remind);
|
||||
|
||||
return recurringTransaction;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user