#24 Transaction import: rules for automatic account matching

This commit is contained in:
2021-09-02 02:30:24 +02:00
parent 70218ad7dc
commit d88e2583b5
22 changed files with 184 additions and 52 deletions

View File

@@ -11,6 +11,10 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
@RestController
@RequestMapping("accounts")
public class AccountController {
@@ -37,15 +41,22 @@ public class AccountController {
}
@RequestMapping("createAccount")
public ResponseEntity createAccount(String key, String type, String accountGroupName) {
public ResponseEntity createAccount(String key, String type, String accountGroupName, String regexps) {
final String decoded = ControllerUtil.urlDecode(key);
final String decodedGroup = ControllerUtil.urlDecode(accountGroupName);
String decodedRegexps = null;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/createAccount got parameters: %s, %s, %s", decoded, type, decodedGroup));
try {
decodedRegexps = URLDecoder.decode(ControllerUtil.urlDecode(regexps), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
// Cannot happen
}
final ResponseReason responseReason = this.accountService.createAccount(decoded, type, decodedGroup);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/createAccount got parameters: %s, %s, %s, %s", decoded, type, decodedGroup, decodedRegexps));
}
final ResponseReason responseReason = this.accountService.createAccount(decoded, type, decodedGroup, decodedRegexps);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/createAccount returns with %s", responseReason.name()));
@@ -55,15 +66,22 @@ public class AccountController {
}
@RequestMapping("editAccount")
public ResponseEntity editAccount(Long id, String key, String accountGroupName) {
public ResponseEntity editAccount(Long id, String key, String accountGroupName, String regexps) {
final String decoded = ControllerUtil.urlDecode(key);
final String decodedGroup = ControllerUtil.urlDecode(accountGroupName);
String decodedRegexps = null;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/editAccount got parameters: %s, %s, %s", id, decoded, decodedGroup));
try {
decodedRegexps = URLDecoder.decode(ControllerUtil.urlDecode(regexps), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
// Cannot happen
}
final ResponseReason responseReason = this.accountService.editAccount(id, decoded, decodedGroup);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/editAccount got parameters: %s, %s, %s, %s", id, decoded, decodedGroup, decodedRegexps));
}
final ResponseReason responseReason = this.accountService.editAccount(id, decoded, decodedGroup, decodedRegexps);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/editAccount returns with %s", responseReason.name()));

View File

@@ -73,6 +73,7 @@ public class AccountService {
* @param key the key of the new account
* @param type the type of the new account. Must be one of {@link AccountType}.
* @param accountGroupName the name of the account group to use
* @param regexps the regular expressions to assign to the new account
*
* @return {@link ResponseReason#INVALID_ACCOUNT_TYPE} if the given type is not a valid {@link AccountType}, {@link
* ResponseReason#UNKNOWN_ERROR} if an unexpected error occurs, {@link ResponseReason#OK} if the operation completed
@@ -81,7 +82,7 @@ public class AccountService {
* <code>accountGroupName</code> does not identify a valid account group. Never returns <code>null</code>.
*/
@Transactional(propagation = Propagation.SUPPORTS)
public ResponseReason createAccount(String key, String type, String accountGroupName) {
public ResponseReason createAccount(String key, String type, String accountGroupName, String regexps) {
if (!AccountType.isValidType(type)) {
return ResponseReason.INVALID_ACCOUNT_TYPE;
}
@@ -101,15 +102,16 @@ public class AccountService {
account.setStatus(AccountStatus.OPEN);
// and has a current balance of 0
account.setCurrentBalance(0L);
account.setUploadMatchRegexps(regexps);
try {
this.accountRepository.save(account);
} catch (DataIntegrityViolationException dive) {
LOGGER.error(String.format("Duplicate key! %s|%s|%s", key, type, accountGroupName), dive);
LOGGER.error(String.format("Duplicate key! %s|%s|%s|%s", key, type, accountGroupName, regexps), dive);
return ResponseReason.DUPLICATE_ACCOUNT_KEY;
} catch (Exception e) {
LOGGER.error(String.format("Could not save account %s|%s|%s", key, type, accountGroupName), e);
LOGGER.error(String.format("Could not save account %s|%s|%s|%s", key, type, accountGroupName, regexps), e);
return ResponseReason.UNKNOWN_ERROR;
}
@@ -123,6 +125,7 @@ public class AccountService {
* @param id the id of the account to edit
* @param key the new key of the account
* @param accountGroupName the new name of the account group to use
* @param regexps the regular expressions of the accounts
*
* @return {@link ResponseReason#OK} if the operation completed successfully, {@link ResponseReason#UNKNOWN_ERROR}
* if an unexpected error occurs, {@link ResponseReason#DUPLICATE_ACCOUNT_KEY} if an account with the given key
@@ -131,7 +134,7 @@ public class AccountService {
* if the given id does not identify a valid account. Never returns <code>null</code>.
*/
@Transactional(propagation = Propagation.REQUIRED)
public ResponseReason editAccount(Long id, String key, String accountGroupName) {
public ResponseReason editAccount(Long id, String key, String accountGroupName, String regexps) {
final Account account = this.accountRepository.findById(id).orElse(null);
if(account == null) {
@@ -146,15 +149,16 @@ public class AccountService {
account.setKey(key);
account.setAccountGroup(accountGroup);
account.setUploadMatchRegexps(regexps);
try {
this.accountRepository.save(account);
} catch (DataIntegrityViolationException dive) {
LOGGER.error(String.format("Duplicate key! %s|%s", key, accountGroupName), dive);
LOGGER.error(String.format("Duplicate key! %s|%s|%s", key, accountGroupName, regexps), dive);
return ResponseReason.DUPLICATE_ACCOUNT_KEY;
} catch (Exception e) {
LOGGER.error(String.format("Could not save account %s|%s", key, accountGroupName), e);
LOGGER.error(String.format("Could not save account %s|%s|%s", key, accountGroupName, regexps), e);
return ResponseReason.UNKNOWN_ERROR;
}

View File

@@ -0,0 +1,2 @@
ALTER TABLE account
ADD COLUMN upload_match_regexps VARCHAR(2000);

View File

@@ -31,7 +31,7 @@ public class AccountService_createAccountTest {
// Nothing to do
// Act
ResponseReason response = this.classUnderTest.createAccount(null, null, null);
ResponseReason response = this.classUnderTest.createAccount(null, null, null, null);
// Assert
Assert.assertEquals(ResponseReason.INVALID_ACCOUNT_TYPE, response);
@@ -45,7 +45,7 @@ public class AccountService_createAccountTest {
.thenReturn(Mockito.mock(AccountGroup.class));
// Act
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1");
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1", null);
// Assert
Assert.assertEquals(ResponseReason.UNKNOWN_ERROR, response);
@@ -58,7 +58,7 @@ public class AccountService_createAccountTest {
.thenReturn(Mockito.mock(AccountGroup.class));
// Act
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1");
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1", null);
// Assert
Assert.assertEquals(ResponseReason.OK, response);
@@ -73,7 +73,7 @@ public class AccountService_createAccountTest {
.thenReturn(null);
// Act
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1");
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1", null);
// Assert
Assert.assertEquals(ResponseReason.ACCOUNT_GROUP_NOT_FOUND, response);
@@ -87,7 +87,7 @@ public class AccountService_createAccountTest {
.thenReturn(Mockito.mock(AccountGroup.class));
// Act
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1");
ResponseReason response = this.classUnderTest.createAccount("Test", "BANK", "Group1", null);
// Assert
Assert.assertEquals(ResponseReason.DUPLICATE_ACCOUNT_KEY, response);