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 e378b2a2b14fa3d7adca618449e2db586f375502..0a75c767836998eec85741023ae6e554aa8daf3c 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 e8265d87c84ee1a22751a00a1e7a1d2ee83e7a2c..b4fcbaffaa06622416109d15cb2ae88c2294182d 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 fbe58af003f81d71ba7f3b42dbfe573b8ab4cda8..541a7a2256a17fce19e1afbe9ef3ef403cb6f189 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 fcadb6ad14deda49b639d537c9d3b842b654d5cb..9a525101ccdaa29d3a0691c4f897c9306ed240c3 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>