From 312788f81aa661cfcfd5867b27bfb09fc4f001a4 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Mon, 17 Oct 2022 18:15:14 +0200 Subject: [PATCH] #722 - added new route to handle edit of the current an upcoming repeating occurrences of a transaction --- .../repeating/RepeatingOption.java | 9 ++- .../transactions/TransactionController.java | 65 ++++++++++++++++++- .../TransactionModelAttributes.java | 1 + .../transactions/newTransactionMacros.ftl | 2 +- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/repeating/RepeatingOption.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/repeating/RepeatingOption.java index e378b2a2b..0a75c7678 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/repeating/RepeatingOption.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/repeating/RepeatingOption.java @@ -9,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat; import javax.persistence.*; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.Objects; @@ -96,6 +97,13 @@ public class RepeatingOption this.referringTransactions = referringTransactions; } + public Transaction getFirstReferringTransaction() + { + return this.referringTransactions.stream() + .min(Comparator.comparing(Transaction::getDate)) + .orElseThrow(); + } + public List<LocalDate> getRepeatingDates(LocalDate dateFetchLimit) { List<LocalDate> dates = new ArrayList<>(); @@ -149,7 +157,6 @@ public class RepeatingOption @Override public int hashCode() { - return Objects.hash(ID, startDate, modifier, endOption); } } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java index e8265d87c..b4fcbaffa 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java @@ -273,7 +273,8 @@ public class TransactionController extends BaseController // select first transaction in order to provide correct start date for repeating transactions if(transaction.getRepeatingOption() != null) { - transaction = transaction.getRepeatingOption().getReferringTransactions().get(0); + transaction = transaction.getRepeatingOption().getFirstReferringTransaction(); + model.addAttribute(TransactionModelAttributes.ACTUAL_OCCURRENCE_TRANSACTION_ID, ID); } LocalDate date = dateService.getDateTimeFromCookie(cookieDate); @@ -342,7 +343,7 @@ public class TransactionController extends BaseController // select first transaction in order to provide correct start date for repeating transactions if(transaction.getRepeatingOption() != null) { - transaction = transaction.getRepeatingOption().getReferringTransactions().get(0); + transaction = transaction.getRepeatingOption().getFirstReferringTransaction(); } Transaction transactionCopy = new Transaction(transaction); @@ -399,4 +400,64 @@ public class TransactionController extends BaseController } return ReturnValues.NEW_TRANSACTION; } + + @GetMapping("/{ID}/editFutureRepetitions") + public String editFutureRepetitions(Model model, @PathVariable("ID") Integer ID, @CookieValue("currentDate") String cookieDate) + { + final Optional<Transaction> transactionOptional = transactionService.getRepository().findById(ID); + if(transactionOptional.isEmpty()) + { + throw new ResourceNotFoundException(); + } + + final Transaction existingTransaction = transactionOptional.get(); + if(!existingTransaction.isRepeating()) + { + throw new IllegalArgumentException("Could not edit future occurrences of non-repeating transaction"); + } + final Transaction firstReferringTransaction = existingTransaction.getRepeatingOption().getFirstReferringTransaction(); + + // copy transaction + final Transaction newTransaction = new Transaction(existingTransaction); + newTransaction.setID(null); + newTransaction.setDate(existingTransaction.getDate()); + if(newTransaction.getAccount().getAccountState() != AccountState.FULL_ACCESS) + { + newTransaction.setAccount(accountService.getRepository().findByIsDefault(true)); + } + + // create new repeating option based on the one from the existing transaction but set end option to never + final RepeatingModifier existingModifier = existingTransaction.getRepeatingOption().getModifier(); + final RepeatingOption newRepeatingOption = createRepeatingOption(existingTransaction.getDate(), + existingModifier.getQuantity(), + Localization.getString(existingModifier.getLocalizationKey()), + Localization.getString(new RepeatingEndNever().getLocalizationKey()), + null); + newTransaction.setRepeatingOption(newRepeatingOption); + + // create new repeating option based on the one from the existing transaction but set end option to date + final LocalDate endDate = existingTransaction.getDate().minusDays(1); + final String endDateString = endDate.format(DateTimeFormatter.ofPattern(DateFormatStyle.LONG.getKey()).withLocale(settingsService.getSettings().getLanguage().getLocale())); + final RepeatingOption newRepeatingOptionForExisting = createRepeatingOption(firstReferringTransaction.getDate(), + existingModifier.getQuantity(), + Localization.getString(existingModifier.getLocalizationKey()), + Localization.getString(new RepeatingEndDate(endDate).getLocalizationKey()), + endDateString); + + // delete and re-create existing transaction + transactionService.deleteTransaction(existingTransaction.getID()); + existingTransaction.setID(null); + existingTransaction.setDate(firstReferringTransaction.getDate()); + existingTransaction.setRepeatingOption(newRepeatingOptionForExisting); + transactionService.getRepository().save(existingTransaction); + + final LocalDate date = dateService.getDateTimeFromCookie(cookieDate); + transactionService.prepareModelNewOrEdit(model, false, date, false, newTransaction, accountService.getAllActivatedAccountsAsc()); + + if(newTransaction.isTransfer()) + { + return ReturnValues.NEW_TRANSFER; + } + return ReturnValues.NEW_TRANSACTION; + } } \ No newline at end of file diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionModelAttributes.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionModelAttributes.java index fbe58af00..541a7a225 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionModelAttributes.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionModelAttributes.java @@ -21,4 +21,5 @@ public class TransactionModelAttributes public static final String ACCOUNTS = "accounts"; public static final String TRANSACTION = "transaction"; public static final String SUGGESTIONS_JSON = "suggestionsJSON"; + public static final String ACTUAL_OCCURRENCE_TRANSACTION_ID = "actualOccurrenceTransactionId"; } diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionMacros.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionMacros.ftl index fcadb6ad1..9a525101c 100644 --- a/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionMacros.ftl +++ b/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionMacros.ftl @@ -197,7 +197,7 @@ </#if> <#if isEdit> - <@header.buttonLink url='/transactions/' + transaction.ID?c + '/editFutureRepetitions' icon='move_up' localizationKey='repeating.button.edit.future' id='button-transaction-edit-future-occurrences' color='background-blue-baby' classes="${buttonEditFutureClasses}"/> + <@header.buttonLink url='/transactions/' + actualOccurrenceTransactionId?c + '/editFutureRepetitions' icon='move_up' localizationKey='repeating.button.edit.future' id='button-transaction-edit-future-occurrences' color='background-blue-baby' classes="${buttonEditFutureClasses}"/> </#if> </div> </div> -- GitLab