diff --git a/src/main/java/de/financer/ResponseReason.java b/src/main/java/de/financer/ResponseReason.java
index d531686..8e87790 100644
--- a/src/main/java/de/financer/ResponseReason.java
+++ b/src/main/java/de/financer/ResponseReason.java
@@ -7,7 +7,6 @@ public enum ResponseReason {
OK(HttpStatus.OK),
UNKNOWN_ERROR(HttpStatus.INTERNAL_SERVER_ERROR),
INVALID_ACCOUNT_TYPE(HttpStatus.INTERNAL_SERVER_ERROR),
- INVALID_ACCOUNT_KEY(HttpStatus.INTERNAL_SERVER_ERROR),
FROM_ACCOUNT_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR),
TO_ACCOUNT_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR),
FROM_AND_TO_ACCOUNT_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR),
diff --git a/src/main/java/de/financer/controller/AccountController.java b/src/main/java/de/financer/controller/AccountController.java
index 12e318f..9c37805 100644
--- a/src/main/java/de/financer/controller/AccountController.java
+++ b/src/main/java/de/financer/controller/AccountController.java
@@ -10,9 +10,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-
@RestController
@RequestMapping("accounts")
public class AccountController {
@@ -24,7 +21,7 @@ public class AccountController {
@RequestMapping("getByKey")
public Account getAccountByKey(String key) {
- final String decoded = URLDecoder.decode(key, StandardCharsets.UTF_8);
+ final String decoded = ControllerUtil.urlDecode(key);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/getAccountByKey got parameter: %s", decoded));
@@ -40,7 +37,7 @@ public class AccountController {
@RequestMapping("createAccount")
public ResponseEntity createAccount(String key, String type) {
- final String decoded = URLDecoder.decode(key, StandardCharsets.UTF_8);
+ final String decoded = ControllerUtil.urlDecode(key);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/createAccount got parameters: %s, %s", decoded, type));
@@ -57,7 +54,7 @@ public class AccountController {
@RequestMapping("closeAccount")
public ResponseEntity closeAccount(String key) {
- final String decoded = URLDecoder.decode(key, StandardCharsets.UTF_8);
+ final String decoded = ControllerUtil.urlDecode(key);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/closeAccount got parameters: %s", decoded));
@@ -74,7 +71,7 @@ public class AccountController {
@RequestMapping("openAccount")
public ResponseEntity openAccount(String key) {
- final String decoded = URLDecoder.decode(key, StandardCharsets.UTF_8);
+ final String decoded = ControllerUtil.urlDecode(key);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/openAccount got parameters: %s", decoded));
diff --git a/src/main/java/de/financer/controller/ControllerUtil.java b/src/main/java/de/financer/controller/ControllerUtil.java
new file mode 100644
index 0000000..bf5711e
--- /dev/null
+++ b/src/main/java/de/financer/controller/ControllerUtil.java
@@ -0,0 +1,22 @@
+package de.financer.controller;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+public class ControllerUtil {
+ /**
+ * This method decodes the given URL encoded string, e.g. replaces %20 with a space.
+ *
+ * @param toDecode the string to decode
+ * @return the decoded string in UTF-8 or, if UTF-8 is not available for whatever reason, the encoded string
+ */
+ public static final String urlDecode(String toDecode) {
+ try {
+ return URLDecoder.decode(toDecode, StandardCharsets.UTF_8.name());
+ }
+ catch (UnsupportedEncodingException e) {
+ return toDecode;
+ }
+ }
+}
diff --git a/src/main/java/de/financer/controller/RecurringTransactionController.java b/src/main/java/de/financer/controller/RecurringTransactionController.java
index dc8ba26..623d6e1 100644
--- a/src/main/java/de/financer/controller/RecurringTransactionController.java
+++ b/src/main/java/de/financer/controller/RecurringTransactionController.java
@@ -35,7 +35,7 @@ public class RecurringTransactionController {
@RequestMapping("getAllForAccount")
public Iterable getAllForAccount(String accountKey) {
- final String decoded = URLDecoder.decode(accountKey, StandardCharsets.UTF_8);
+ final String decoded = ControllerUtil.urlDecode(accountKey);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/recurringTransactions/getAllForAccount got parameter: %s", decoded));
@@ -55,8 +55,8 @@ public class RecurringTransactionController {
String intervalType, String firstOccurrence,
String lastOccurrence
) {
- final String decodedFrom = URLDecoder.decode(fromAccountKey, StandardCharsets.UTF_8);
- final String decodedTo = URLDecoder.decode(toAccountKey, StandardCharsets.UTF_8);
+ final String decodedFrom = ControllerUtil.urlDecode(fromAccountKey);
+ final String decodedTo = ControllerUtil.urlDecode(toAccountKey);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String
diff --git a/src/main/java/de/financer/controller/TransactionController.java b/src/main/java/de/financer/controller/TransactionController.java
index bce51d3..61ab109 100644
--- a/src/main/java/de/financer/controller/TransactionController.java
+++ b/src/main/java/de/financer/controller/TransactionController.java
@@ -28,7 +28,7 @@ public class TransactionController {
@RequestMapping("getAllForAccount")
public Iterable getAllForAccount(String accountKey) {
- final String decoded = URLDecoder.decode(accountKey, StandardCharsets.UTF_8);
+ final String decoded = ControllerUtil.urlDecode(accountKey);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/transactions/getAllForAccount got parameter: %s", decoded));
@@ -41,8 +41,8 @@ public class TransactionController {
public ResponseEntity createTransaction(String fromAccountKey, String toAccountKey, Long amount, String date,
String description
) {
- final String decodedFrom = URLDecoder.decode(fromAccountKey, StandardCharsets.UTF_8);
- final String decodedTo = URLDecoder.decode(toAccountKey, StandardCharsets.UTF_8);
+ final String decodedFrom = ControllerUtil.urlDecode(fromAccountKey);
+ final String decodedTo = ControllerUtil.urlDecode(toAccountKey);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String
diff --git a/src/main/java/de/financer/service/AccountService.java b/src/main/java/de/financer/service/AccountService.java
index fba36b4..bcea422 100644
--- a/src/main/java/de/financer/service/AccountService.java
+++ b/src/main/java/de/financer/service/AccountService.java
@@ -55,10 +55,9 @@ public class AccountService {
* This method creates new account with the given key and type. The account has status {@link AccountStatus#OPEN OPEN}
* and a current balance of 0.
*
- * @param key the key of the new account. Must begin with account.
+ * @param key the key of the new account
* @param type the type of the new account. Must be one of {@link AccountType}.
* @return {@link ResponseReason#INVALID_ACCOUNT_TYPE} if the given type is not a valid {@link AccountType},
- * {@link ResponseReason#INVALID_ACCOUNT_KEY} if the given key does not conform to the format specification,
* {@link ResponseReason#UNKNOWN_ERROR} if an unexpected error occurs and
* {@link ResponseReason#OK} if the operation completed successfully. Never returns null.
*/
@@ -68,10 +67,6 @@ public class AccountService {
return ResponseReason.INVALID_ACCOUNT_TYPE;
}
- if (!StringUtils.startsWith(key, "accounts.")) {
- return ResponseReason.INVALID_ACCOUNT_KEY;
- }
-
final Account account = new Account();
account.setKey(key);
@@ -105,10 +100,6 @@ public class AccountService {
// Visible for unit tests
/* package */ ResponseReason setAccountStatus(String key, AccountStatus accountStatus) {
- if (!StringUtils.startsWith(key, "accounts.")) {
- return ResponseReason.INVALID_ACCOUNT_KEY;
- }
-
final Account account = this.accountRepository.findByKey(key);
if (account == null) {
diff --git a/src/main/resources/database/common/V3_0_0__accountRename.sql b/src/main/resources/database/common/V3_0_0__accountRename.sql
new file mode 100644
index 0000000..12652c7
--- /dev/null
+++ b/src/main/resources/database/common/V3_0_0__accountRename.sql
@@ -0,0 +1,88 @@
+-- Rename all accounts to proper names instead of the artificial 'accounts.' names
+UPDATE account
+SET "key" = 'Check account'
+WHERE "key" = 'accounts.checkaccount';
+
+UPDATE account
+SET "key" = 'Income'
+WHERE "key" = 'accounts.income'
+
+UPDATE account
+SET "key" = 'Cash'
+WHERE "key" = 'accounts.cash';
+
+UPDATE account
+SET "key" = 'Start'
+WHERE "key" = 'accounts.start';
+
+UPDATE account
+SET "key" = 'Rent'
+WHERE "key" = 'accounts.rent';
+
+UPDATE account
+SET "key" = 'FVS'
+WHERE "key" = 'accounts.fvs';
+
+UPDATE account
+SET "key" = 'Car'
+WHERE "key" = 'accounts.car';
+
+UPDATE account
+SET "key" = 'Gas'
+WHERE "key" = 'accounts.gas';
+
+UPDATE account
+SET "key" = 'Alimony'
+WHERE "key" = 'accounts.alimony';
+
+UPDATE account
+SET "key" = 'Electricity/Water'
+WHERE "key" = 'accounts.electricitywater';
+
+UPDATE account
+SET "key" = 'Mobile'
+WHERE "key" = 'accounts.mobile';
+
+UPDATE account
+SET "key" = 'Internet'
+WHERE "key" = 'accounts.internet';
+
+UPDATE account
+SET "key" = 'Legal insurance'
+WHERE "key" = 'accounts.legalinsurance';
+
+UPDATE account
+SET "key" = 'Netflix'
+WHERE "key" = 'accounts.netflix';
+
+UPDATE account
+SET "key" = 'Hetzner'
+WHERE "key" = 'accounts.hetzner';
+
+UPDATE account
+SET "key" = 'Fees'
+WHERE "key" = 'accounts.fees';
+
+UPDATE account
+SET "key" = 'Food'
+WHERE "key" = 'accounts.food';
+
+UPDATE account
+SET "key" = 'Food (external)'
+WHERE "key" = 'accounts.foodexternal';
+
+UPDATE account
+SET "key" = 'Child'
+WHERE "key" = 'accounts.child';
+
+UPDATE account
+SET "key" = 'Credit card'
+WHERE "key" = 'accounts.creditcard';
+
+UPDATE account
+SET "key" = 'Student loan'
+WHERE "key" = 'accounts.studentloan';
+
+UPDATE account
+SET "key" = 'Bed'
+WHERE "key" = 'accounts.bed';
\ No newline at end of file
diff --git a/src/test/java/de/financer/controller/integration/RecurringTransactionService_createRecurringTransactionIntegrationTest.java b/src/test/java/de/financer/controller/integration/RecurringTransactionService_createRecurringTransactionIntegrationTest.java
index 6f8fc25..c64e6ae 100644
--- a/src/test/java/de/financer/controller/integration/RecurringTransactionService_createRecurringTransactionIntegrationTest.java
+++ b/src/test/java/de/financer/controller/integration/RecurringTransactionService_createRecurringTransactionIntegrationTest.java
@@ -36,8 +36,8 @@ public class RecurringTransactionService_createRecurringTransactionIntegrationTe
@Test
public void test_createRecurringTransaction() throws Exception {
final MvcResult mvcRequest = this.mockMvc.perform(get("/recurringTransactions/createRecurringTransaction")
- .param("fromAccountKey", "accounts.income")
- .param("toAccountKey", "accounts.checkaccount")
+ .param("fromAccountKey", "Income")
+ .param("toAccountKey", "Check account")
.param("amount", "250000")
.param("description", "Monthly rent")
.param("holidayWeekendType", "SAME_DAY")
diff --git a/src/test/java/de/financer/service/AccountService_createAccountTest.java b/src/test/java/de/financer/service/AccountService_createAccountTest.java
index 38daec8..ed4e007 100644
--- a/src/test/java/de/financer/service/AccountService_createAccountTest.java
+++ b/src/test/java/de/financer/service/AccountService_createAccountTest.java
@@ -32,25 +32,13 @@ public class AccountService_createAccountTest {
Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_TYPE, response);
}
- @Test
- public void test_createAccount_INVALID_ACCOUNT_KEY() {
- // Arrange
- // Nothing to do
-
- // Act
- ResponseReason response = this.classUnderTest.createAccount(null, "BANK");
-
- // Assert
- Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_KEY, response);
- }
-
@Test
public void test_createAccount_UNKNOWN_ERROR() {
// Arrange
Mockito.doThrow(new NullPointerException()).when(this.accountRepository).save(Mockito.any(Account.class));
// Act
- ResponseReason response = this.classUnderTest.createAccount("accounts.test", "BANK");
+ ResponseReason response = this.classUnderTest.createAccount("Test", "BANK");
// Assert
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
@@ -62,11 +50,11 @@ public class AccountService_createAccountTest {
// Nothing to do
// Act
- ResponseReason response = this.classUnderTest.createAccount("accounts.test", "BANK");
+ ResponseReason response = this.classUnderTest.createAccount("Test", "BANK");
// Assert
Assert.assertEquals(ResponseReason.OK, response);
Mockito.verify(this.accountRepository, Mockito.times(1))
- .save(ArgumentMatchers.argThat((acc) -> "accounts.test".equals(acc.getKey())));
+ .save(ArgumentMatchers.argThat((acc) -> "Test".equals(acc.getKey())));
}
}
diff --git a/src/test/java/de/financer/service/AccountService_setAccountStatusTest.java b/src/test/java/de/financer/service/AccountService_setAccountStatusTest.java
index 880fff8..6c0ce2c 100644
--- a/src/test/java/de/financer/service/AccountService_setAccountStatusTest.java
+++ b/src/test/java/de/financer/service/AccountService_setAccountStatusTest.java
@@ -21,25 +21,13 @@ public class AccountService_setAccountStatusTest {
@Mock
private AccountRepository accountRepository;
- @Test
- public void test_setAccountStatus_INVALID_ACCOUNT_KEY() {
- // Arrange
- // Nothing to do
-
- // Act
- ResponseReason response = this.classUnderTest.setAccountStatus(null, AccountStatus.CLOSED);
-
- // Assert
- Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_KEY, response);
- }
-
@Test
public void test_setAccountStatus_ACCOUNT_NOT_FOUND() {
// Arrange
// Nothing to do
// Act
- ResponseReason response = this.classUnderTest.setAccountStatus("accounts.test", AccountStatus.CLOSED);
+ ResponseReason response = this.classUnderTest.setAccountStatus("Test", AccountStatus.CLOSED);
// Assert
Assert.assertEquals(ResponseReason.ACCOUNT_NOT_FOUND, response);
@@ -52,7 +40,7 @@ public class AccountService_setAccountStatusTest {
Mockito.doThrow(new NullPointerException()).when(this.accountRepository).save(Mockito.any(Account.class));
// Act
- ResponseReason response = this.classUnderTest.setAccountStatus("accounts.test", AccountStatus.CLOSED);
+ ResponseReason response = this.classUnderTest.setAccountStatus("Test", AccountStatus.CLOSED);
// Assert
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
@@ -64,7 +52,7 @@ public class AccountService_setAccountStatusTest {
Mockito.when(this.accountRepository.findByKey(Mockito.anyString())).thenReturn(new Account());
// Act
- ResponseReason response = this.classUnderTest.setAccountStatus("accounts.test", AccountStatus.CLOSED);
+ ResponseReason response = this.classUnderTest.setAccountStatus("Test", AccountStatus.CLOSED);
// Assert
Assert.assertEquals(ResponseReason.OK, response);
diff --git a/src/test/java/de/financer/task/SendRecurringTransactionReminderTaskTest.java b/src/test/java/de/financer/task/SendRecurringTransactionReminderTaskTest.java
index 7af9de9..844178d 100644
--- a/src/test/java/de/financer/task/SendRecurringTransactionReminderTaskTest.java
+++ b/src/test/java/de/financer/task/SendRecurringTransactionReminderTaskTest.java
@@ -36,9 +36,9 @@ public class SendRecurringTransactionReminderTaskTest {
public void test_sendReminder() {
// Arrange
final Collection recurringTransactions = Arrays.asList(
- createRecurringTransaction("Test booking 1", "accounts.income", "accounts.bank", Long.valueOf(250000)),
- createRecurringTransaction("Test booking 2", "accounts.bank", "accounts.rent", Long.valueOf(41500)),
- createRecurringTransaction("Test booking 3", "accounts.bank", "accounts.cash", Long.valueOf(5000))
+ 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))
);
Mockito.when(this.recurringTransactionService.getAllDueToday()).thenReturn(recurringTransactions);
diff --git a/src/test/resources/database/hsqldb/integration/V999_99_00__testdata.sql b/src/test/resources/database/hsqldb/integration/V999_99_00__testdata.sql
index c55b95e..ef84e78 100644
--- a/src/test/resources/database/hsqldb/integration/V999_99_00__testdata.sql
+++ b/src/test/resources/database/hsqldb/integration/V999_99_00__testdata.sql
@@ -1,13 +1,13 @@
-- Accounts
INSERT INTO account ("key", type, status, current_balance)
-VALUES ('accounts.convenience', 'EXPENSE', 'OPEN', 0);
+VALUES ('Convenience', 'EXPENSE', 'OPEN', 0);
--Recurring transactions
INSERT INTO recurring_transaction (from_account_id, to_account_id, description, amount, interval_type, first_occurrence, holiday_weekend_type)
-VALUES ((SELECT ID FROM account WHERE "key" = 'accounts.income'), (SELECT ID FROM account WHERE "key" = 'accounts.checkaccount'), 'Pay', 250000, 'MONTHLY', '2019-01-15', 'NEXT_WORKDAY');
+VALUES ((SELECT ID FROM account WHERE "key" = 'Income'), (SELECT ID FROM account WHERE "key" = 'Check account'), 'Pay', 250000, 'MONTHLY', '2019-01-15', 'NEXT_WORKDAY');
INSERT INTO recurring_transaction (from_account_id, to_account_id, description, amount, interval_type, first_occurrence, holiday_weekend_type)
-VALUES ((SELECT ID FROM account WHERE "key" = 'accounts.cash'), (SELECT ID FROM account WHERE "key" = 'accounts.convenience'), 'Pretzel', 170, 'DAILY', '2019-02-20', 'SAME_DAY');
+VALUES ((SELECT ID FROM account WHERE "key" = 'Cash'), (SELECT ID FROM account WHERE "key" = 'Convenience'), 'Pretzel', 170, 'DAILY', '2019-02-20', 'SAME_DAY');
INSERT INTO recurring_transaction (from_account_id, to_account_id, description, amount, interval_type, first_occurrence, last_occurrence, holiday_weekend_type)
-VALUES ((SELECT ID FROM account WHERE "key" = 'accounts.cash'), (SELECT ID FROM account WHERE "key" = 'accounts.foodexternal'), 'McDonalds Happy Meal', 399, 'WEEKLY', '2019-02-20', '2019-03-20', 'SAME_DAY');
\ No newline at end of file
+VALUES ((SELECT ID FROM account WHERE "key" = 'Cash'), (SELECT ID FROM account WHERE "key" = 'Food (external)'), 'McDonalds Happy Meal', 399, 'WEEKLY', '2019-02-20', '2019-03-20', 'SAME_DAY');
\ No newline at end of file