List of usage examples for org.joda.time LocalDate isAfter
public boolean isAfter(ReadablePartial partial)
From source file:com.gst.portfolio.savings.domain.interest.PostingPeriod.java
License:Apache License
private static List<CompoundingPeriod> compoundingPeriodsInPostingPeriod( final LocalDateInterval postingPeriodInterval, final SavingsCompoundingInterestPeriodType interestPeriodType, final List<EndOfDayBalance> allEndOfDayBalances, final LocalDate upToInterestCalculationDate) { final List<CompoundingPeriod> compoundingPeriods = new ArrayList<>(); CompoundingPeriod compoundingPeriod = null; switch (interestPeriodType) { case INVALID: break;//w w w . jav a 2s .c om case DAILY: compoundingPeriod = DailyCompoundingPeriod.create(postingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); break; case MONTHLY: final LocalDate postingPeriodEndDate = postingPeriodInterval.endDate(); LocalDate periodStartDate = postingPeriodInterval.startDate(); LocalDate periodEndDate = periodStartDate; while (!periodStartDate.isAfter(postingPeriodEndDate) && !periodEndDate.isAfter(postingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate); if (periodEndDate.isAfter(postingPeriodEndDate)) { periodEndDate = postingPeriodEndDate; } final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate); if (postingPeriodInterval.contains(compoundingPeriodInterval)) { compoundingPeriod = MonthlyCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); } // move periodStartDate forward to day after this period periodStartDate = periodEndDate.plusDays(1); } break; // case WEEKLY: // break; // case BIWEEKLY: // break; case QUATERLY: final LocalDate qPostingPeriodEndDate = postingPeriodInterval.endDate(); periodStartDate = postingPeriodInterval.startDate(); periodEndDate = periodStartDate; while (!periodStartDate.isAfter(qPostingPeriodEndDate) && !periodEndDate.isAfter(qPostingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate); if (periodEndDate.isAfter(qPostingPeriodEndDate)) { periodEndDate = qPostingPeriodEndDate; } final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate); if (postingPeriodInterval.contains(compoundingPeriodInterval)) { compoundingPeriod = QuarterlyCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); } // move periodStartDate forward to day after this period periodStartDate = periodEndDate.plusDays(1); } break; case BI_ANNUAL: final LocalDate bPostingPeriodEndDate = postingPeriodInterval.endDate(); periodStartDate = postingPeriodInterval.startDate(); periodEndDate = periodStartDate; while (!periodStartDate.isAfter(bPostingPeriodEndDate) && !periodEndDate.isAfter(bPostingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate); if (periodEndDate.isAfter(bPostingPeriodEndDate)) { periodEndDate = bPostingPeriodEndDate; } final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate); if (postingPeriodInterval.contains(compoundingPeriodInterval)) { compoundingPeriod = BiAnnualCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); } // move periodStartDate forward to day after this period periodStartDate = periodEndDate.plusDays(1); } break; case ANNUAL: final LocalDate aPostingPeriodEndDate = postingPeriodInterval.endDate(); periodStartDate = postingPeriodInterval.startDate(); periodEndDate = periodStartDate; while (!periodStartDate.isAfter(aPostingPeriodEndDate) && !periodEndDate.isAfter(aPostingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate); if (periodEndDate.isAfter(aPostingPeriodEndDate)) { periodEndDate = aPostingPeriodEndDate; } final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate); if (postingPeriodInterval.contains(compoundingPeriodInterval)) { compoundingPeriod = AnnualCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); } // move periodStartDate forward to day after this period periodStartDate = periodEndDate.plusDays(1); } break; // case NO_COMPOUNDING_SIMPLE_INTEREST: // break; } return compoundingPeriods; }
From source file:com.gst.portfolio.savings.domain.RecurringDepositAccount.java
License:Apache License
public void prematureClosure(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> actualChanges) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME + DepositsApiConstants.preMatureCloseAction); final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status); if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.in.active.state"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }// www .j a v a 2 s . co m } final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command .localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); if (closedDate.isBefore(getActivationLocalDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (isAccountLocked(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.lockin.period"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isAfter(maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.before.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isAfter(tenantsTodayDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (isAccountLocked(calculateMaturityDate())) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "deposit.period.must.be.greater.than.lock.in.period", "Deposit period must be greater than account lock-in period."); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } final List<SavingsAccountTransaction> savingsAccountTransactions = retreiveListOfTransactions(); if (savingsAccountTransactions.size() > 0) { final SavingsAccountTransaction accountTransaction = savingsAccountTransactions .get(savingsAccountTransactions.size() - 1); if (accountTransaction.isAfter(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.last.transaction.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } } validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_CLOSE_ACCOUNT, closedDate); this.status = SavingsAccountStatusType.PRE_MATURE_CLOSURE.getValue(); final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName); final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId); this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType); /* * // withdraw deposit amount before closing the account final Money * transactionAmountMoney = Money.of(this.currency, * this.getAccountBalance()); final SavingsAccountTransaction withdraw = * SavingsAccountTransaction.withdrawal(this, office(), paymentDetail, * closedDate, transactionAmountMoney, new Date()); * this.transactions.add(withdraw); */ actualChanges.put(SavingsApiConstants.statusParamName, SavingsEnumerations.status(this.status)); actualChanges.put(SavingsApiConstants.localeParamName, command.locale()); actualChanges.put(SavingsApiConstants.dateFormatParamName, command.dateFormat()); actualChanges.put(SavingsApiConstants.closedOnDateParamName, closedDate.toString(fmt)); this.rejectedOnDate = null; this.rejectedBy = null; this.withdrawnOnDate = null; this.withdrawnBy = null; this.closedOnDate = closedDate.toDate(); this.closedBy = currentUser; this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.RecurringDepositAccount.java
License:Apache License
public void close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> actualChanges) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.closeAction); final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status); if (!SavingsAccountStatusType.MATURED.hasStateOf(currentStatus) && this.maturityDate() != null) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.in.matured.state"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }//w w w .j a v a2s.c o m } final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command .localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); if (closedDate.isBefore(getActivationLocalDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (maturityDate() != null && closedDate.isBefore(maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.account.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isAfter(tenantsTodayDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } final List<SavingsAccountTransaction> savingsAccountTransactions = retreiveListOfTransactions(); if (savingsAccountTransactions.size() > 0) { final SavingsAccountTransaction accountTransaction = savingsAccountTransactions .get(savingsAccountTransactions.size() - 1); if (accountTransaction.isAfter(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.last.transaction.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } } validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_CLOSE_ACCOUNT, closedDate); this.status = SavingsAccountStatusType.CLOSED.getValue(); final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName); final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId); this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType); /* * // withdraw deposit amount before closing the account final Money * transactionAmountMoney = Money.of(this.currency, * this.getAccountBalance()); final SavingsAccountTransaction withdraw = * SavingsAccountTransaction.withdrawal(this, office(), paymentDetail, * closedDate, transactionAmountMoney, new Date()); * this.transactions.add(withdraw); */ actualChanges.put(SavingsApiConstants.statusParamName, SavingsEnumerations.status(this.status)); actualChanges.put(SavingsApiConstants.localeParamName, command.locale()); actualChanges.put(SavingsApiConstants.dateFormatParamName, command.dateFormat()); actualChanges.put(SavingsApiConstants.closedOnDateParamName, closedDate.toString(fmt)); this.rejectedOnDate = null; this.rejectedBy = null; this.withdrawnOnDate = null; this.withdrawnBy = null; this.closedOnDate = closedDate.toDate(); this.closedBy = currentUser; this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.RecurringDepositAccount.java
License:Apache License
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth, final LocalDate closeDate) { LocalDate interestPostingUpToDate = maturityDate(); if (interestPostingUpToDate == null) { interestPostingUpToDate = closeDate; }/*ww w. jav a 2 s .c o m*/ final MathContext mc = MathContext.DECIMAL64; boolean isInterestTransfer = false; LocalDate postInterestOnDate = null; final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate.minusDays(1), isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate); Money interestPostedToDate = Money.zero(this.currency); boolean recalucateDailyBalanceDetails = false; for (final PostingPeriod interestPostingPeriod : postingPeriods) { LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); interestPostingTransactionDate = interestPostingTransactionDate.isAfter(interestPostingUpToDate) ? interestPostingUpToDate : interestPostingTransactionDate; final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); interestPostedToDate = interestPostedToDate.plus(interestEarnedToBePostedForPeriod); final SavingsAccountTransaction postingTransaction = findInterestPostingTransactionFor( interestPostingTransactionDate); if (postingTransaction == null) { final SavingsAccountTransaction newPostingTransaction = SavingsAccountTransaction.interestPosting( this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod, interestPostingPeriod.isUserPosting()); addTransaction(newPostingTransaction); recalucateDailyBalanceDetails = true; } else { final boolean correctionRequired = postingTransaction .hasNotAmount(interestEarnedToBePostedForPeriod); if (correctionRequired) { postingTransaction.reverse(); final SavingsAccountTransaction newPostingTransaction = SavingsAccountTransaction .interestPosting(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod, interestPostingPeriod.isUserPosting()); addTransaction(newPostingTransaction); recalucateDailyBalanceDetails = true; } } } applyWithholdTaxForDepositAccounts(interestPostingUpToDate, recalucateDailyBalanceDetails); if (recalucateDailyBalanceDetails) { // update existing transactions so derived balance fields are // correct. recalculateDailyBalances(Money.zero(this.currency), interestPostingUpToDate); } this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.RecurringDepositAccount.java
License:Apache License
public void generateSchedule(final PeriodFrequencyType frequency, final Integer recurringEvery, final Calendar calendar) { this.depositScheduleInstallments.clear(); LocalDate installmentDate = null; if (this.isCalendarInherited()) { installmentDate = CalendarUtils.getNextScheduleDate(calendar, accountSubmittedOrActivationDate()); } else {//from ww w. ja v a 2 s.c om installmentDate = depositStartDate(); } int installmentNumber = 1; final LocalDate maturityDate = calcualteScheduleTillDate(frequency, recurringEvery); final BigDecimal depositAmount = this.recurringDetail.mandatoryRecommendedDepositAmount(); while (maturityDate.isAfter(installmentDate)) { final RecurringDepositScheduleInstallment installment = RecurringDepositScheduleInstallment .installment(this, installmentNumber, installmentDate.toDate(), depositAmount); addDepositScheduleInstallment(installment); installmentDate = DepositAccountUtils.calculateNextDepositDate(installmentDate, frequency, recurringEvery); installmentNumber += 1; } updateDepositAmount(); }
From source file:com.gst.portfolio.savings.domain.RecurringDepositAccount.java
License:Apache License
public void updateOverduePayments(final LocalDate todayDate) { LocalDate overdueUptoDate = this.maturityDate(); if (overdueUptoDate == null || overdueUptoDate.isAfter(todayDate)) { overdueUptoDate = todayDate;/*from ww w . j a v a2s . c o m*/ } final List<RecurringDepositScheduleInstallment> installments = depositScheduleInstallments(); int noOfOverdueInstallments = 0; Money totalOverdueAmount = Money.zero(getCurrency()); for (RecurringDepositScheduleInstallment installment : installments) { if (installment.isNotFullyPaidOff() && overdueUptoDate.isAfter(installment.dueDate())) { noOfOverdueInstallments++; totalOverdueAmount = totalOverdueAmount .plus(installment.getDepositAmountOutstanding(getCurrency())); } } this.recurringDetail.updateOverdueDetails(noOfOverdueInstallments, totalOverdueAmount); }
From source file:com.gst.portfolio.savings.domain.RecurringDepositScheduleInstallment.java
License:Apache License
private boolean isLatePayment(final LocalDate transactionDate) { return transactionDate.isAfter(dueDate()); }
From source file:com.gst.portfolio.savings.domain.SavingsAccount.java
License:Apache License
public void postInterest(final MathContext mc, final LocalDate interestPostingUpToDate, final boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth, final LocalDate postInterestOnDate) { final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate);/*from w w w. j a v a 2s .com*/ Money interestPostedToDate = Money.zero(this.currency); boolean recalucateDailyBalanceDetails = false; boolean applyWithHoldTax = isWithHoldTaxApplicableForInterestPosting(); final List<SavingsAccountTransaction> withholdTransactions = new ArrayList<>(); withholdTransactions.addAll(findWithHoldTransactions()); for (final PostingPeriod interestPostingPeriod : postingPeriods) { final LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); if (!interestPostingTransactionDate.isAfter(interestPostingUpToDate)) { interestPostedToDate = interestPostedToDate.plus(interestEarnedToBePostedForPeriod); final SavingsAccountTransaction postingTransaction = findInterestPostingTransactionFor( interestPostingTransactionDate); if (postingTransaction == null) { SavingsAccountTransaction newPostingTransaction; if (interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency))) { newPostingTransaction = SavingsAccountTransaction.interestPosting(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod, interestPostingPeriod.isUserPosting()); } else { newPostingTransaction = SavingsAccountTransaction.overdraftInterest(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod.negated(), interestPostingPeriod.isUserPosting()); } addTransaction(newPostingTransaction); if (applyWithHoldTax) { createWithHoldTransaction(interestEarnedToBePostedForPeriod.getAmount(), interestPostingTransactionDate); } recalucateDailyBalanceDetails = true; } else { boolean correctionRequired = false; if (postingTransaction.isInterestPostingAndNotReversed()) { correctionRequired = postingTransaction.hasNotAmount(interestEarnedToBePostedForPeriod); } else { correctionRequired = postingTransaction .hasNotAmount(interestEarnedToBePostedForPeriod.negated()); } if (correctionRequired) { boolean applyWithHoldTaxForOldTransaction = false; postingTransaction.reverse(); final SavingsAccountTransaction withholdTransaction = findTransactionFor( interestPostingTransactionDate, withholdTransactions); if (withholdTransaction != null) { withholdTransaction.reverse(); applyWithHoldTaxForOldTransaction = true; } SavingsAccountTransaction newPostingTransaction; if (interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency))) { newPostingTransaction = SavingsAccountTransaction.interestPosting(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod, interestPostingPeriod.isUserPosting()); } else { newPostingTransaction = SavingsAccountTransaction.overdraftInterest(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod.negated(), interestPostingPeriod.isUserPosting()); } addTransaction(newPostingTransaction); if (applyWithHoldTaxForOldTransaction) { createWithHoldTransaction(interestEarnedToBePostedForPeriod.getAmount(), interestPostingTransactionDate); } recalucateDailyBalanceDetails = true; } } } } if (recalucateDailyBalanceDetails) { // no openingBalance concept supported yet but probably will to // allow // for migrations. final Money openingAccountBalance = Money.zero(this.currency); // update existing transactions so derived balance fields are // correct. recalculateDailyBalances(openingAccountBalance, interestPostingUpToDate); } this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.SavingsAccount.java
License:Apache License
private boolean isDateInTheFuture(final LocalDate transactionDate) { return transactionDate.isAfter(DateUtils.getLocalDateOfTenant()); }
From source file:com.gst.portfolio.savings.domain.SavingsAccount.java
License:Apache License
private void validateUnassignDate(final SavingsOfficerAssignmentHistory latestHistoryRecord, final LocalDate unassignDate) { final LocalDate today = DateUtils.getLocalDateOfTenant(); if (latestHistoryRecord.getStartDate().isAfter(unassignDate)) { final String errorMessage = "The Savings officer Unassign date(" + unassignDate + ") cannot be before its assignment date (" + latestHistoryRecord.getStartDate() + ")."; throw new SavingsOfficerUnassignmentDateException("cannot.be.before.assignment.date", errorMessage, getId(), getSavingsOfficer().getId(), latestHistoryRecord.getStartDate(), unassignDate); } else if (unassignDate.isAfter(today)) { final String errorMessage = "The Savings Officer Unassign date (" + unassignDate + ") cannot be in the future."; throw new SavingsOfficerUnassignmentDateException("cannot.be.a.future.date", errorMessage, unassignDate);//from ww w .jav a2 s. com } }