From e602fa6b3c202fb73d6dfa48e27bc363aa3749eb Mon Sep 17 00:00:00 2001 From: jmarta Date: Tue, 26 Sep 2023 12:54:42 +0200 Subject: [PATCH] FINERACT-1983: Date handling improvements - general --- ...WritePlatformServiceJpaRepositoryImpl.java | 7 +- .../glaccount/domain/TrialBalance.java | 6 +- .../commands/domain/CommandSource.java | 6 +- .../jobs/PurgeProcessedCommandsTasklet.java | 2 +- .../BusinessDateReadPlatformServiceImpl.java | 5 +- .../BusinessDateWritePlatformServiceImpl.java | 6 +- .../core/data/DataValidatorBuilder.java | 9 +- .../core/domain/LocalDateInterval.java | 5 +- .../core/service/DateUtils.java | 4 - .../core/service/database/JdbcJavaType.java | 3 +- .../jobs/SendAsynchronousEventsTasklet.java | 2 +- .../repository/domain/ExternalEvent.java | 2 +- .../holiday/service/HolidayUtil.java | 39 ++--- .../organisation/office/domain/Office.java | 7 +- .../portfolio/calendar/data/CalendarData.java | 6 +- .../data/CalendarHistoryDataWrapper.java | 8 +- .../portfolio/calendar/domain/Calendar.java | 38 ++--- .../calendar/domain/CalendarEntityType.java | 49 ++++--- .../calendar/domain/CalendarHistory.java | 17 ++- .../calendar/service/CalendarUtils.java | 14 +- .../portfolio/client/domain/Client.java | 39 ++--- .../floatingrates/data/FloatingRateDTO.java | 3 +- .../floatingrates/domain/FloatingRate.java | 12 +- .../group/data/GroupGeneralData.java | 2 +- .../group/domain/StaffAssignmentHistory.java | 3 +- .../portfolio/tax/data/TaxComponentData.java | 3 +- .../tax/data/TaxComponentHistoryData.java | 6 +- .../tax/data/TaxGroupMappingsData.java | 6 +- .../portfolio/tax/domain/TaxComponent.java | 2 +- .../tax/domain/TaxComponentHistory.java | 6 +- .../tax/domain/TaxGroupMappings.java | 6 +- .../service/AppUserConstants.java | 2 + .../service/InvestorAccountingHelper.java | 3 +- .../ExternalAssetOwnersWriteServiceImpl.java | 4 +- .../loanaccount/data/DisbursementData.java | 11 +- .../data/LoanTermVariationsData.java | 7 +- .../data/LoanTermVariationsDataWrapper.java | 5 +- .../portfolio/loanaccount/domain/Loan.java | 23 ++- .../loanaccount/domain/LoanCharge.java | 25 ++-- .../domain/LoanDisbursementDetails.java | 12 +- ...oanRepaymentScheduleProcessingWrapper.java | 3 +- .../domain/LoanSummaryWrapper.java | 3 +- .../loanaccount/domain/LoanTransaction.java | 36 ++--- .../domain/LoanTransactionComparator.java | 59 ++++---- .../data/LoanSchedulePeriodData.java | 27 +--- .../domain/LoanApplicationTerms.java | 9 +- .../service/AccountingProcessorHelper.java | 8 +- ...lEntryRunningBalanceUpdateServiceImpl.java | 5 +- ...WritePlatformServiceJpaRepositoryImpl.java | 14 +- ...WritePlatformServiceJpaRepositoryImpl.java | 3 +- .../fineract/cob/domain/LoanAccountLock.java | 4 +- .../fineract/cob/loan/LoanCOBPartitioner.java | 4 +- .../cob/loan/LoanLockingServiceImpl.java | 4 +- .../AsyncLoanCOBExecutorServiceImpl.java | 5 +- .../InlineLoanCOBExecutorServiceImpl.java | 5 +- .../bulkimport/domain/ImportDocument.java | 2 +- .../importhandler/ImportHandlerUtils.java | 3 +- .../SharedProductsSheetPopulator.java | 3 +- .../campaigns/email/domain/EmailCampaign.java | 36 ++--- ...mpaignWritePlatformCommandHandlerImpl.java | 72 +++------- .../campaigns/jobs/TenantDateTimeUtil.java | 41 ------ .../ExecuteReportMailingJobsTasklet.java | 2 +- ...ailOutboundWithCampaignMessageTasklet.java | 16 +-- ...SmsOutboundWithCampaignMessageTasklet.java | 14 +- .../core/domain/AuditorAwareImpl.java | 9 +- ...auIntegrationWritePlatformServiceImpl.java | 2 +- .../domain/FineractEntityToEntityMapping.java | 8 +- .../FineractEntityAccessWriteServiceImpl.java | 11 +- .../service/updatenpa/UpdateNpaTasklet.java | 5 +- .../security/domain/TFAccessToken.java | 11 +- ...SpringSecurityPlatformSecurityContext.java | 2 +- .../data/InteropTransactionsData.java | 3 +- ...WritePlatformServiceJpaRepositoryImpl.java | 19 ++- .../data/CashierTransactionDataValidator.java | 36 ++--- .../TellerCommandFromApiJsonDeserializer.java | 3 +- .../ExecuteStandingInstructionsTasklet.java | 4 +- ...ountTransfersWritePlatformServiceImpl.java | 3 +- .../CalendarReadPlatformServiceImpl.java | 6 +- .../InternalClientInformationApiResource.java | 4 +- .../client/domain/ClientNonPerson.java | 4 +- .../ClientChargeWritePlatformServiceImpl.java | 6 +- ...WritePlatformServiceJpaRepositoryImpl.java | 20 +-- .../LoanDelinquencyDomainServiceImpl.java | 23 +-- ...WritePlatformServiceJpaRepositoryImpl.java | 26 ++-- .../data/InterestRateChartData.java | 3 +- .../data/InterestRateChartDataValidator.java | 14 +- .../domain/InterestRateChartSlabFields.java | 7 +- .../InternalLoanInformationApiResource.java | 8 +- .../domain/LoanAccountDomainServiceJpa.java | 28 ++-- .../domain/LoanRepaymentDataComparator.java | 30 ---- .../domain/LoanTermVariationsComparator.java | 6 +- ...RepaymentScheduleTransactionProcessor.java | 30 ++-- ...edPaymentScheduleTransactionProcessor.java | 10 +- ...RepaymentScheduleTransactionProcessor.java | 5 +- ...RepaymentScheduleTransactionProcessor.java | 7 +- ...RepaymentScheduleTransactionProcessor.java | 5 +- ...RepaymentScheduleTransactionProcessor.java | 9 +- .../service/GuarantorDomainServiceImpl.java | 2 +- ...ritePlatformServiceJpaRepositoryIImpl.java | 2 +- .../ApplyHolidaysToLoansTasklet.java | 14 +- .../TransferFeeChargeForLoansTasklet.java | 4 +- .../domain/AbstractLoanScheduleGenerator.java | 135 +++++++++--------- ...gBalanceInterestLoanScheduleGenerator.java | 3 +- .../domain/DefaultScheduledDateGenerator.java | 28 ++-- .../service/LoanScheduleAssembler.java | 50 +++---- ...cheduleCalculationPlatformServiceImpl.java | 8 +- ...heduleHistoryWritePlatformServiceImpl.java | 4 +- .../LoanRescheduleRequestDataValidator.java | 11 +- ...nReschedulePreviewPlatformServiceImpl.java | 5 +- ...heduleRequestWritePlatformServiceImpl.java | 10 +- ...ateLoanScheduleQueryFromApiJsonHelper.java | 4 +- ...anApplicationCommandFromApiJsonHelper.java | 7 +- .../LoanAccrualWritePlatformServiceImpl.java | 42 +++--- ...WritePlatformServiceJpaRepositoryImpl.java | 17 +-- .../service/LoanArrearsAgingServiceImpl.java | 9 +- .../LoanCalculateRepaymentPastDueService.java | 3 +- .../service/LoanChargeAssembler.java | 3 +- .../LoanChargeWritePlatformServiceImpl.java | 37 +++-- .../service/LoanReadPlatformServiceImpl.java | 15 +- .../loanaccount/service/LoanUtilService.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 33 ++--- .../LoanProductReadPlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 7 +- .../portfolio/meeting/domain/Meeting.java | 4 +- .../search/data/SearchConditions.java | 24 ++-- .../AccountEntityServiceForSavingsImpl.java | 4 +- ...ountEntityServiceForShareAccountsImpl.java | 3 +- .../shareaccounts/domain/ShareAccount.java | 15 +- .../ShareAccountDataSerializer.java | 18 +-- .../ShareAccountReadPlatformServiceImpl.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../shareproducts/domain/ShareProduct.java | 10 +- .../ShareProductDividendAssembler.java | 3 +- .../tax/serialization/TaxValidator.java | 4 +- .../PurgeProcessedCommandsTaskletTest.java | 2 +- .../loanaccount/domain/LoanTest.java | 65 +++++++++ .../AccountingScenarioIntegrationTest.java | 12 +- .../ClientLoanIntegrationTest.java | 3 +- ...OverlappingDownPaymentInstallmentTest.java | 3 +- ...lTransactionOnChargeSubmittedDateTest.java | 5 +- .../LoanAccrualTransactionReversalTest.java | 3 +- ...ipleDisbursementRepaymentScheduleTest.java | 3 +- ...oductWithDownPaymentConfigurationTest.java | 3 +- .../OfficeIntegrationTest.java | 3 +- .../common/SchedulerJobHelper.java | 6 +- .../common/loans/LoanTransactionHelper.java | 3 +- .../datatable/DatatableAdvancedQueryTest.java | 6 +- 147 files changed, 797 insertions(+), 1028 deletions(-) delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/TenantDateTimeUtil.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentDataComparator.java diff --git a/fineract-core/src/main/java/org/apache/fineract/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java b/fineract-core/src/main/java/org/apache/fineract/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java index 44541cc4c..55764af8e 100644 --- a/fineract-core/src/main/java/org/apache/fineract/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-core/src/main/java/org/apache/fineract/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java @@ -66,15 +66,14 @@ public class GLClosureWritePlatformServiceJpaRepositoryImpl implements GLClosure final Office office = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId); // TODO: Get Tenant specific date // ensure closure date is not in the future - final LocalDate todaysDate = DateUtils.getBusinessLocalDate(); final LocalDate closureDate = command.localDateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue()); - if (closureDate.isAfter(todaysDate)) { + if (DateUtils.isDateInTheFuture(closureDate)) { throw new GLClosureInvalidException(GlClosureInvalidReason.FUTURE_DATE, closureDate); } // shouldn't be before an existing accounting closure final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(officeId); if (latestGLClosure != null) { - if (latestGLClosure.getClosingDate().isAfter(closureDate)) { + if (DateUtils.isAfter(latestGLClosure.getClosingDate(), closureDate)) { throw new GLClosureInvalidException(GlClosureInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate()); } } @@ -122,7 +121,7 @@ public class GLClosureWritePlatformServiceJpaRepositoryImpl implements GLClosure **/ final LocalDate closureDate = glClosure.getClosingDate(); final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(glClosure.getOffice().getId()); - if (latestGLClosure.getClosingDate().isAfter(closureDate)) { + if (DateUtils.isAfter(latestGLClosure.getClosingDate(), closureDate)) { throw new GLClosureInvalidDeleteException(latestGLClosure.getOffice().getId(), latestGLClosure.getOffice().getName(), latestGLClosure.getClosingDate()); } diff --git a/fineract-core/src/main/java/org/apache/fineract/accounting/glaccount/domain/TrialBalance.java b/fineract-core/src/main/java/org/apache/fineract/accounting/glaccount/domain/TrialBalance.java index b80c51b0f..757d37774 100644 --- a/fineract-core/src/main/java/org/apache/fineract/accounting/glaccount/domain/TrialBalance.java +++ b/fineract-core/src/main/java/org/apache/fineract/accounting/glaccount/domain/TrialBalance.java @@ -30,6 +30,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; @Entity @Table(name = "m_trial_balance") @@ -70,9 +71,8 @@ public class TrialBalance extends AbstractPersistableCustom { } TrialBalance other = (TrialBalance) obj; return Objects.equals(other.officeId, officeId) && Objects.equals(other.glAccountId, glAccountId) - && Objects.equals(other.amount, amount) && other.entryDate.compareTo(entryDate) == 0 ? Boolean.TRUE - : Boolean.FALSE && other.transactionDate.compareTo(transactionDate) == 0 ? Boolean.TRUE - : Boolean.FALSE && Objects.equals(other.closingBalance, closingBalance); + && Objects.equals(other.amount, amount) && DateUtils.isEqual(other.entryDate, entryDate) + && DateUtils.isEqual(other.transactionDate, transactionDate) && Objects.equals(other.closingBalance, closingBalance); } @Override diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java index 707007aa4..c56a7c02b 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java @@ -133,7 +133,7 @@ public class CommandSource extends AbstractPersistableCustom { this.subResourceId = subResourceId; this.commandAsJson = commandSerializedAsJson; this.maker = maker; - this.madeOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + this.madeOnDate = DateUtils.getAuditOffsetDateTime(); this.status = status; this.idempotencyKey = idempotencyKey; } @@ -314,13 +314,13 @@ public class CommandSource extends AbstractPersistableCustom { public void markAsChecked(final AppUser checker) { this.checker = checker; - this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + this.checkedOnDate = DateUtils.getAuditOffsetDateTime(); this.status = CommandProcessingResultType.PROCESSED.getValue(); } public void markAsRejected(final AppUser checker) { this.checker = checker; - this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + this.checkedOnDate = DateUtils.getAuditOffsetDateTime(); this.status = CommandProcessingResultType.REJECTED.getValue(); } diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTasklet.java b/fineract-core/src/main/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTasklet.java index ba81cdfbb..de7dc4bf2 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTasklet.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTasklet.java @@ -43,7 +43,7 @@ public class PurgeProcessedCommandsTasklet implements Tasklet { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { try { Long numberOfDaysForPurgeCriteria = configurationDomainService.retrieveProcessedCommandsPurgeDaysCriteria(); - OffsetDateTime dateForPurgeCriteria = DateUtils.getOffsetDateTimeOfTenant().minusDays(numberOfDaysForPurgeCriteria); + OffsetDateTime dateForPurgeCriteria = DateUtils.getAuditOffsetDateTime().minusDays(numberOfDaysForPurgeCriteria); repository.deleteOlderEventsWithStatus(CommandProcessingResultType.PROCESSED.getValue(), dateForPurgeCriteria); } catch (Exception e) { log.error("Error occurred while purging processed commands: ", e); diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateReadPlatformServiceImpl.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateReadPlatformServiceImpl.java index 9b7d2f2c8..00a871128 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateReadPlatformServiceImpl.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateReadPlatformServiceImpl.java @@ -19,7 +19,6 @@ package org.apache.fineract.infrastructure.businessdate.service; import java.time.LocalDate; -import java.time.ZoneId; import java.util.HashMap; import java.util.List; import java.util.Optional; @@ -70,8 +69,7 @@ public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlat @Override public HashMap getBusinessDates() { HashMap businessDateMap = new HashMap<>(); - ZoneId zone = DateUtils.getDateTimeZoneOfTenant(); - LocalDate tenantDate = LocalDate.now(zone); + LocalDate tenantDate = DateUtils.getLocalDateOfTenant(); businessDateMap.put(BusinessDateType.BUSINESS_DATE, tenantDate); businessDateMap.put(BusinessDateType.COB_DATE, tenantDate); if (configurationDomainService.isBusinessDateEnabled()) { @@ -80,7 +78,6 @@ public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlat businessDateMap.put(BusinessDateType.valueOf(businessDateData.getType()), businessDateData.getDate()); } } - return businessDateMap; } } diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateWritePlatformServiceImpl.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateWritePlatformServiceImpl.java index b1671ebb0..9b25f4937 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateWritePlatformServiceImpl.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/businessdate/service/BusinessDateWritePlatformServiceImpl.java @@ -132,15 +132,11 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl private void updateBusinessDate(BusinessDate businessDate, LocalDate newDate, Map changes) { LocalDate oldDate = businessDate.getDate(); - if (!hasChange(oldDate, newDate)) { + if (DateUtils.isEqual(oldDate, newDate)) { return; } businessDate.setDate(newDate); repository.save(businessDate); changes.put(businessDate.getType().name(), newDate); } - - private boolean hasChange(@NotNull LocalDate oldDate, @NotNull LocalDate date) { - return (date.isBefore(oldDate) || date.isAfter(oldDate)); - } } diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/DataValidatorBuilder.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/DataValidatorBuilder.java index 29bb485e1..da2a1abd5 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/DataValidatorBuilder.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/DataValidatorBuilder.java @@ -32,6 +32,7 @@ import net.fortuna.ical4j.model.property.RRule; import net.fortuna.ical4j.validate.ValidationException; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.quartz.CronExpression; import org.springframework.util.ObjectUtils; @@ -1045,7 +1046,7 @@ public class DataValidatorBuilder { if (this.value != null && date != null) { final LocalDate dateVal = (LocalDate) this.value; - if (date.isAfter(dateVal)) { + if (DateUtils.isAfter(date, dateVal)) { final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".") .append(this.parameter).append(".is.less.than.date"); final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter) @@ -1065,7 +1066,7 @@ public class DataValidatorBuilder { if (this.value != null && date != null) { final LocalDate dateVal = (LocalDate) this.value; - if (date.isBefore(dateVal)) { + if (DateUtils.isBefore(date, dateVal)) { final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".") .append(this.parameter).append(".is.greater.than.date"); final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter) @@ -1085,7 +1086,7 @@ public class DataValidatorBuilder { if (this.value != null && date != null) { final LocalDate dateVal = (LocalDate) this.value; - if (dateVal.isAfter(date)) { + if (DateUtils.isAfter(dateVal, date)) { final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".") .append(this.parameter).append(".is.greater.than.date"); final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter) @@ -1105,7 +1106,7 @@ public class DataValidatorBuilder { if (this.value != null && date != null) { final LocalDate dateVal = (LocalDate) this.value; - if (!dateVal.isEqual(date)) { + if (!DateUtils.isEqual(dateVal, date)) { final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".") .append(this.parameter).append(".is.not.equal.to.date"); final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter) diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/LocalDateInterval.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/LocalDateInterval.java index 5ad239f23..82a8e7e26 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/LocalDateInterval.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/LocalDateInterval.java @@ -22,6 +22,7 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.fineract.infrastructure.core.service.DateUtils; public class LocalDateInterval { @@ -66,11 +67,11 @@ public class LocalDateInterval { } private boolean isBetweenInclusive(final LocalDate start, final LocalDate end, final LocalDate target) { - return !target.isBefore(start) && !target.isAfter(end); + return !DateUtils.isBefore(target, start) && !DateUtils.isAfter(target, end); } public boolean fallsBefore(final LocalDate dateToCheck) { - return this.endDate.isBefore(dateToCheck); + return DateUtils.isBefore(this.endDate, dateToCheck); } @Override diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java index ca45f22d1..6c5f518e1 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java @@ -70,10 +70,6 @@ public final class DateUtils { return truncate == null ? now : now.truncatedTo(truncate); } - public static OffsetDateTime getOffsetDateTimeOfTenantWithMostPrecision() { - return getOffsetDateTimeOfTenant(null); - } - public static OffsetDateTime getOffsetDateTimeOfTenant() { return getOffsetDateTimeOfTenant(null); } diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/JdbcJavaType.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/JdbcJavaType.java index a03834de0..929debb92 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/JdbcJavaType.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/JdbcJavaType.java @@ -20,6 +20,7 @@ package org.apache.fineract.infrastructure.core.service.database; import com.google.common.collect.ImmutableList; import jakarta.validation.constraints.NotNull; +import java.io.Serializable; import java.sql.JDBCType; import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException; @@ -272,7 +273,7 @@ public enum JdbcJavaType { } @com.google.errorprone.annotations.Immutable - private static final class DialectType { + private static final class DialectType implements Serializable { @NotNull private final JDBCType jdbcType; diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/jobs/SendAsynchronousEventsTasklet.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/jobs/SendAsynchronousEventsTasklet.java index 4217620ac..ac9d01a25 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/jobs/SendAsynchronousEventsTasklet.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/jobs/SendAsynchronousEventsTasklet.java @@ -99,7 +99,7 @@ public class SendAsynchronousEventsTasklet implements Tasklet { } private void markEventsAsSent(List eventIds) { - OffsetDateTime sentAt = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + OffsetDateTime sentAt = DateUtils.getAuditOffsetDateTime(); // Partitioning dataset to avoid exception: PreparedStatement can have at most 65,535 parameters List> partitions = Lists.partition(eventIds, 5_000); diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/repository/domain/ExternalEvent.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/repository/domain/ExternalEvent.java index d281facac..b3ff59f18 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/repository/domain/ExternalEvent.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/repository/domain/ExternalEvent.java @@ -80,7 +80,7 @@ public class ExternalEvent extends AbstractPersistableCustom { this.data = data; this.idempotencyKey = idempotencyKey; this.aggregateRootId = aggregateRootId; - this.createdAt = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + this.createdAt = DateUtils.getAuditOffsetDateTime(); this.status = ExternalEventStatus.TO_BE_SENT; this.businessDate = DateUtils.getBusinessLocalDate(); } diff --git a/fineract-core/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java b/fineract-core/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java index 92401cd4e..ad912c495 100644 --- a/fineract-core/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java +++ b/fineract-core/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java @@ -20,6 +20,7 @@ package org.apache.fineract.organisation.holiday.service; import java.time.LocalDate; import java.util.List; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.holiday.domain.Holiday; import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO; @@ -30,47 +31,29 @@ public final class HolidayUtil { } public static LocalDate getRepaymentRescheduleDateToIfHoliday(LocalDate repaymentDate, final List holidays) { - for (final Holiday holiday : holidays) { - if (repaymentDate.equals(holiday.getFromDate()) || repaymentDate.equals(holiday.getToDate()) - || (repaymentDate.isAfter(holiday.getFromDate()) && repaymentDate.isBefore(holiday.getToDate()))) { - repaymentDate = getRepaymentRescheduleDateIfHoliday(repaymentDate, holidays); - } - } - return repaymentDate; - } - - private static LocalDate getRepaymentRescheduleDateIfHoliday(final LocalDate repaymentDate, final List holidays) { - - for (final Holiday holiday : holidays) { - if (repaymentDate.equals(holiday.getFromDate()) || repaymentDate.equals(holiday.getToDate()) - || (repaymentDate.isAfter(holiday.getFromDate()) && repaymentDate.isBefore(holiday.getToDate()))) { - // should be take from holiday - return holiday.getRepaymentsRescheduledTo(); + if (isHoliday(repaymentDate, holiday)) { + repaymentDate = holiday.getRepaymentsRescheduledTo(); } } return repaymentDate; } public static boolean isHoliday(final LocalDate date, final List holidays) { - for (final Holiday holiday : holidays) { - if (date.isEqual(holiday.getFromDate()) || date.isEqual(holiday.getToDate()) - || (date.isAfter(holiday.getFromDate()) && date.isBefore(holiday.getToDate()))) { - return true; - } - } - - return false; + return getApplicableHoliday(date, holidays) != null; } public static Holiday getApplicableHoliday(final LocalDate repaymentDate, final List holidays) { - Holiday referedHoliday = null; for (final Holiday holiday : holidays) { - if (!repaymentDate.isBefore(holiday.getFromDate()) && !repaymentDate.isAfter(holiday.getToDate())) { - referedHoliday = holiday; + if (isHoliday(repaymentDate, holiday)) { + return holiday; } } - return referedHoliday; + return null; + } + + public static boolean isHoliday(LocalDate date, Holiday holiday) { + return !DateUtils.isBefore(date, holiday.getFromDate()) && !DateUtils.isAfter(date, holiday.getToDate()); } public static void updateRepaymentRescheduleDateToWorkingDayIfItIsHoliday(final AdjustedDateDetailsDTO adjustedDateDetailsDTO, diff --git a/fineract-core/src/main/java/org/apache/fineract/organisation/office/domain/Office.java b/fineract-core/src/main/java/org/apache/fineract/organisation/office/domain/Office.java index 29c61c1f5..f6bd289c5 100644 --- a/fineract-core/src/main/java/org/apache/fineract/organisation/office/domain/Office.java +++ b/fineract-core/src/main/java/org/apache/fineract/organisation/office/domain/Office.java @@ -39,6 +39,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; import org.apache.fineract.infrastructure.core.domain.ExternalId; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.organisation.office.exception.CannotUpdateOfficeWithParentOfficeSameAsSelf; import org.apache.fineract.organisation.office.exception.RootOfficeParentCannotBeUpdated; @@ -155,11 +156,11 @@ public class Office extends AbstractPersistableCustom implements Serializable { } public boolean isOpeningDateBefore(final LocalDate baseDate) { - return getOpeningLocalDate().isBefore(baseDate); + return DateUtils.isBefore(getOpeningLocalDate(), baseDate); } - public boolean isOpeningDateAfter(final LocalDate activationLocalDate) { - return getOpeningLocalDate().isAfter(activationLocalDate); + public boolean isOpeningDateAfter(final LocalDate baseDate) { + return DateUtils.isAfter(getOpeningLocalDate(), baseDate); } public LocalDate getOpeningLocalDate() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java index 9a5211a47..8426c3b97 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java @@ -28,6 +28,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType; import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy; import org.apache.fineract.portfolio.calendar.domain.CalendarType; @@ -377,12 +378,11 @@ public final class CalendarData implements Serializable { } public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) { - return this.startDate != null && compareDate != null - && (this.startDate.isBefore(compareDate) || this.startDate.equals(compareDate)); + return this.startDate != null && compareDate != null && !DateUtils.isAfter(this.startDate, compareDate); } public boolean isEndDateAfterOrEqual(final LocalDate compareDate) { - return this.endDate != null && compareDate != null && (this.endDate.isAfter(compareDate) || this.endDate.isEqual(compareDate)); + return this.endDate != null && compareDate != null && !DateUtils.isBefore(this.endDate, compareDate); } public boolean isBetweenStartAndEndDate(final LocalDate compareDate) { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java index c0568c845..a932ceaeb 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java @@ -20,10 +20,10 @@ package org.apache.fineract.portfolio.calendar.data; import java.time.LocalDate; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.calendar.domain.CalendarHistory; public class CalendarHistoryDataWrapper { @@ -37,16 +37,16 @@ public class CalendarHistoryDataWrapper { @Override public int compare(CalendarHistory calendarHistory1, CalendarHistory calendarHistory2) { - return calendarHistory1.getEndDateLocalDate().compareTo(calendarHistory2.getEndDateLocalDate()); + return DateUtils.compare(calendarHistory1.getEndDate(), calendarHistory2.getEndDate()); } }; - Collections.sort(this.calendarHistoryList, orderByDate); + this.calendarHistoryList.sort(orderByDate); } public CalendarHistory getCalendarHistory(final LocalDate dueRepaymentPeriodDate) { CalendarHistory calendarHistory = null; for (CalendarHistory history : this.calendarHistoryList) { - if (history.getEndDateLocalDate().isAfter(dueRepaymentPeriodDate)) { + if (DateUtils.isAfter(history.getEndDate(), dueRepaymentPeriodDate)) { calendarHistory = history; break; } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java index ed8419b63..227bc1917 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java @@ -175,23 +175,19 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom { } public Map updateStartDateAndDerivedFeilds(final LocalDate newMeetingStartDate) { - final Map actualChanges = new LinkedHashMap<>(9); final LocalDate currentDate = DateUtils.getLocalDateOfTenant(); - - if (newMeetingStartDate.isBefore(currentDate)) { + if (DateUtils.isBefore(newMeetingStartDate, currentDate)) { final String defaultUserMessage = "New meeting effective from date cannot be in past"; throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newMeetingStartDate, getStartDateLocalDate()); } else if (isStartDateAfter(newMeetingStartDate) && isStartDateBeforeOrEqual(currentDate)) { - // new meeting date should be on or after start date or current - // date + // new meeting date should be on or after start date or current date final String defaultUserMessage = "New meeting effective from date cannot be a date before existing meeting start date"; throw new CalendarDateException("new.start.date.before.existing.date", defaultUserMessage, newMeetingStartDate, getStartDateLocalDate()); } else { - actualChanges.put(CalendarSupportedParameters.START_DATE.getValue(), newMeetingStartDate.toString()); this.startDate = newMeetingStartDate; @@ -200,33 +196,25 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom { * recurring day and update it if it is changed. For weekly type is weekday and for monthly type it is day * of the month */ - CalendarFrequencyType calendarFrequencyType = CalendarUtils.getFrequency(this.recurrence); Integer interval = CalendarUtils.getInterval(this.recurrence); Integer repeatsOnDay = null; - /* - * Repeats on day, need to derive based on the start date - */ - + // Repeats on day, need to derive based on the start date if (calendarFrequencyType.isWeekly()) { repeatsOnDay = newMeetingStartDate.get(ChronoField.DAY_OF_WEEK); } else if (calendarFrequencyType.isMonthly()) { repeatsOnDay = newMeetingStartDate.getDayOfMonth(); } - // TODO cover other recurrence also this.recurrence = constructRecurrence(calendarFrequencyType, interval, repeatsOnDay, null); - } return actualChanges; - } public Map update(final JsonCommand command, final Boolean areActiveEntitiesSynced) { - final Map actualChanges = new LinkedHashMap<>(9); if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.TITLE.getValue(), this.title)) { @@ -234,13 +222,11 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom { actualChanges.put(CalendarSupportedParameters.TITLE.getValue(), newValue); this.title = StringUtils.defaultIfEmpty(newValue, null); } - if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue(), this.description)) { final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue()); actualChanges.put(CalendarSupportedParameters.DESCRIPTION.getValue(), newValue); this.description = StringUtils.defaultIfEmpty(newValue, null); } - if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.LOCATION.getValue(), this.location)) { final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.LOCATION.getValue()); actualChanges.put(CalendarSupportedParameters.LOCATION.getValue(), newValue); @@ -251,12 +237,11 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom { final String localeAsInput = command.locale(); final String startDateParamName = CalendarSupportedParameters.START_DATE.getValue(); if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartDateLocalDate())) { - final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName); final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName); final LocalDate currentDate = DateUtils.getLocalDateOfTenant(); - if (newValue.isBefore(currentDate)) { + if (DateUtils.isBefore(newValue, currentDate)) { final String defaultUserMessage = "New meeting effective from date cannot be in past"; throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newValue, getStartDateLocalDate()); } else if (isStartDateAfter(newValue) && isStartDateBeforeOrEqual(currentDate)) { @@ -472,24 +457,19 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom { } public boolean isStartDateBefore(final LocalDate compareDate) { - if (this.startDate != null && compareDate != null && getStartDateLocalDate().isBefore(compareDate)) { - return true; - } - return false; + return startDate != null && DateUtils.isBefore(startDate, compareDate); } public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) { - return this.startDate != null && compareDate != null - && (getStartDateLocalDate().isBefore(compareDate) || getStartDateLocalDate().equals(compareDate)); + return startDate != null && !DateUtils.isAfter(startDate, compareDate); } public boolean isStartDateAfter(final LocalDate compareDate) { - return this.startDate != null && compareDate != null && getStartDateLocalDate().isAfter(compareDate); + return compareDate != null && DateUtils.isAfter(startDate, compareDate); } public boolean isEndDateAfterOrEqual(final LocalDate compareDate) { - return this.endDate != null && compareDate != null - && (getEndDateLocalDate().isAfter(compareDate) || getEndDateLocalDate().isEqual(compareDate)); + return compareDate != null && !DateUtils.isBefore(endDate, compareDate); } public boolean isBetweenStartAndEndDate(final LocalDate compareDate) { @@ -585,7 +565,7 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom { // validate with history details. for (CalendarHistory history : history()) { if (history.isBetweenStartAndEndDate(compareDate)) { - return CalendarUtils.isValidRedurringDate(history.getRecurrence(), history.getStartDateLocalDate(), compareDate, + return CalendarUtils.isValidRedurringDate(history.getRecurrence(), history.getStartDate(), compareDate, isSkipRepaymentOnFirstMonth, numberOfDays); } } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarEntityType.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarEntityType.java index f65593dd8..e487c9253 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarEntityType.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarEntityType.java @@ -88,51 +88,63 @@ public enum CalendarEntityType { } public static boolean isGroup(final Integer value) { - return CalendarEntityType.GROUPS.value.equals(value) ? true : false; + return CalendarEntityType.GROUPS.value.equals(value); } public static boolean isGroup(final String name) { - return CalendarEntityType.GROUPS.name().equalsIgnoreCase(name) ? true : false; + return CalendarEntityType.GROUPS.name().equalsIgnoreCase(name); } public static boolean isCenter(final Integer value) { - return CalendarEntityType.CENTERS.value.equals(value) ? true : false; + return CalendarEntityType.CENTERS.value.equals(value); } public static boolean isCenter(final String name) { - return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name) ? true : false; + return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name); } public static boolean isLoan(final Integer value) { - return CalendarEntityType.LOANS.value.equals(value) ? true : false; + return CalendarEntityType.LOANS.value.equals(value); } public static boolean isLoan(final String name) { - return CalendarEntityType.LOANS.name().equalsIgnoreCase(name) ? true : false; + return CalendarEntityType.LOANS.name().equalsIgnoreCase(name); } public static boolean isClient(final Integer value) { - return CalendarEntityType.CLIENTS.value.equals(value) ? true : false; + return CalendarEntityType.CLIENTS.value.equals(value); } public static boolean isClient(final String name) { - return CalendarEntityType.CLIENTS.name().equalsIgnoreCase(name) ? true : false; + return CalendarEntityType.CLIENTS.name().equalsIgnoreCase(name); + } + + public static boolean isSavings(final Integer value) { + return CalendarEntityType.SAVINGS.value.equals(value); + } + + public static boolean isSavings(final String name) { + return CalendarEntityType.SAVINGS.name().equalsIgnoreCase(name); } public boolean isCenter() { - return this.value.equals(CalendarEntityType.CENTERS.getValue()); + return this == CENTERS; } public boolean isGroup() { - return this.value.equals(CalendarEntityType.GROUPS.getValue()); + return this == GROUPS; } public boolean isLoan() { - return this.value.equals(CalendarEntityType.LOANS.getValue()); + return this == LOANS; } public boolean isClient() { - return this.value.equals(CalendarEntityType.CLIENTS.getValue()); + return this == CLIENTS; + } + + public boolean isSavings() { + return this == SAVINGS; } private static final Map entityNameToEnumMap = new HashMap<>(); @@ -146,17 +158,4 @@ public enum CalendarEntityType { public static CalendarEntityType getEntityType(String entityType) { return entityNameToEnumMap.get(entityType.toLowerCase()); } - - public static boolean isSavings(final Integer value) { - return CalendarEntityType.SAVINGS.value.equals(value) ? true : false; - } - - public static boolean isSavings(final String name) { - return CalendarEntityType.SAVINGS.name().equalsIgnoreCase(name) ? true : false; - } - - public boolean isSavings() { - return this.value.equals(CalendarEntityType.SAVINGS.getValue()); - } - } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarHistory.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarHistory.java index 7c40d8f25..cd2f1fbfe 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarHistory.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarHistory.java @@ -25,6 +25,7 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.time.LocalDate; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; @Entity @Table(name = "m_calendar_history") @@ -95,26 +96,24 @@ public class CalendarHistory extends AbstractPersistableCustom { return this.recurrence; } - public LocalDate getStartDateLocalDate() { + public LocalDate getStartDate() { return this.startDate; } - public LocalDate getEndDateLocalDate() { + public LocalDate getEndDate() { return this.endDate; } - public boolean isEndDateAfterOrEqual(final LocalDate compareDate) { - return this.endDate != null && compareDate != null - && (getEndDateLocalDate().isAfter(compareDate) || getEndDateLocalDate().isEqual(compareDate)); + public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) { + return this.startDate != null && compareDate != null && !DateUtils.isAfter(this.startDate, compareDate); } - public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) { - return this.startDate != null && compareDate != null - && (getStartDateLocalDate().isBefore(compareDate) || getStartDateLocalDate().equals(compareDate)); + public boolean isEndDateAfterOrEqual(final LocalDate compareDate) { + return this.endDate != null && compareDate != null && !DateUtils.isBefore(this.endDate, compareDate); } public boolean isBetweenStartAndEndDate(final LocalDate compareDate) { - return isStartDateBeforeOrEqual(compareDate) && (getEndDateLocalDate() == null || isEndDateAfterOrEqual(compareDate)); + return isStartDateBeforeOrEqual(compareDate) && (getEndDate() == null || isEndDateAfterOrEqual(compareDate)); } public void updateEndDate(LocalDate historyCalEndDate) { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java index 486c2fe9a..409ffb088 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java @@ -103,14 +103,14 @@ public final class CalendarUtils { final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant())); final Date seed = convertToiCal4JCompatibleDate(seedDate); final Date nextRecDate = recur.getNextDate(seed, periodStart); - return nextRecDate == null ? null : LocalDateTime.ofInstant(nextRecDate.toInstant(), DateUtils.getSystemZoneId()); + return nextRecDate == null ? null : LocalDateTime.ofInstant(nextRecDate.toInstant(), DateUtils.getDateTimeZoneOfTenant()); } private static LocalDate getNextRecurringDate(final Recur recur, final LocalDate seedDate, final LocalDate startDate) { final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant())); final Date seed = convertToiCal4JCompatibleDate(seedDate.atStartOfDay()); final Date nextRecDate = recur.getNextDate(seed, periodStart); - return nextRecDate == null ? null : LocalDate.ofInstant(nextRecDate.toInstant(), DateUtils.getSystemZoneId()); + return nextRecDate == null ? null : LocalDate.ofInstant(nextRecDate.toInstant(), DateUtils.getDateTimeZoneOfTenant()); } private static Date convertToiCal4JCompatibleDate(final LocalDateTime inputDate) { @@ -125,16 +125,16 @@ public final class CalendarUtils { } public static Collection getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate endDate) { - final LocalDate periodStartDate = DateUtils.getLocalDateOfTenant(); - final LocalDate periodEndDate = (endDate == null) ? DateUtils.getLocalDateOfTenant().plusYears(5) : endDate; + final LocalDate periodEndDate = endDate == null ? periodStartDate.plusYears(5) : endDate; return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate); } public static Collection getRecurringDatesFrom(final String recurringRule, final LocalDate seedDate, final LocalDate startDate) { - final LocalDate periodStartDate = (startDate == null) ? DateUtils.getLocalDateOfTenant() : startDate; - final LocalDate periodEndDate = DateUtils.getLocalDateOfTenant().plusYears(5); + LocalDate currentDate = DateUtils.getLocalDateOfTenant(); + final LocalDate periodStartDate = startDate == null ? currentDate : startDate; + final LocalDate periodEndDate = currentDate.plusYears(5); return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate); } @@ -150,7 +150,6 @@ public final class CalendarUtils { public static Collection getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate periodStartDate, final LocalDate periodEndDate, final int maxCount, boolean isSkippMeetingOnFirstDay, final Integer numberOfDays) { - final Recur recur = CalendarUtils.getICalRecur(recurringRule); return getRecurringDates(recur, seedDate, periodStartDate, periodEndDate, maxCount, isSkippMeetingOnFirstDay, numberOfDays); @@ -173,7 +172,6 @@ public final class CalendarUtils { private static Collection convertToLocalDateList(final DateList dates, final LocalDate seedDate, final PeriodFrequencyType frequencyType, boolean isSkippMeetingOnFirstDay, final Integer numberOfDays) { - final Collection recurringDates = new ArrayList<>(); for (@SuppressWarnings("rawtypes") diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java index ad216bdd8..f1a055199 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java @@ -407,10 +407,6 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom { return ClientStatus.fromInt(this.status).isPending(); } - private boolean isDateInTheFuture(final LocalDate localDate) { - return localDate.isAfter(DateUtils.getBusinessLocalDate()); - } - public boolean isRejected() { return ClientStatus.fromInt(this.status).isRejected(); } @@ -444,49 +440,40 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom { } private void validateActivationDate(final List dataValidationErrors) { - - if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) { - + if (getSubmittedOnDate() != null && DateUtils.isDateInTheFuture(getSubmittedOnDate())) { final String defaultUserMessage = "submitted date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.in.the.future", defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - - if (getActivationLocalDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getActivationLocalDate())) { - + if (getActivationDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getActivationDate())) { final String defaultUserMessage = "submitted date cannot be after the activation date"; final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.activation.date", defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - - if (getReopenedDate() != null && getActivationLocalDate() != null && getReopenedDate().isAfter(getActivationLocalDate())) { - + if (getActivationDate() != null && DateUtils.isAfter(getReopenedDate(), getActivationDate())) { final String defaultUserMessage = "reopened date cannot be after the submittedon date"; final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.reopened.date", defaultUserMessage, ClientApiConstants.reopenedDateParamName, this.reopenedDate); dataValidationErrors.add(error); } - - if (getActivationLocalDate() != null && isDateInTheFuture(getActivationLocalDate())) { - + if (DateUtils.isDateInTheFuture(getActivationDate())) { final String defaultUserMessage = "Activation date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.activationDate.in.the.future", - defaultUserMessage, ClientApiConstants.activationDateParamName, getActivationLocalDate()); + defaultUserMessage, ClientApiConstants.activationDateParamName, getActivationDate()); dataValidationErrors.add(error); } - - if (getActivationLocalDate() != null) { - if (this.office.isOpeningDateAfter(getActivationLocalDate())) { + if (getActivationDate() != null) { + if (this.office.isOpeningDateAfter(getActivationDate())) { final String defaultUserMessage = "Client activation date cannot be a date before the office opening date."; final ApiParameterError error = ApiParameterError.parameterError( "error.msg.clients.activationDate.cannot.be.before.office.activation.date", defaultUserMessage, - ClientApiConstants.activationDateParamName, getActivationLocalDate()); + ClientApiConstants.activationDateParamName, getActivationDate()); dataValidationErrors.add(error); } } @@ -518,14 +505,6 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom { } } - public LocalDate getActivationLocalDate() { - return this.activationDate; - } - - public LocalDate getOfficeJoiningLocalDate() { - return this.officeJoiningDate; - } - public boolean isOfficeIdentifiedBy(final Long officeId) { return this.office.identifiedBy(officeId); } @@ -618,7 +597,7 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom { } public boolean isActivatedAfter(final LocalDate submittedOn) { - return getActivationLocalDate().isAfter(submittedOn); + return DateUtils.isAfter(getActivationDate(), submittedOn); } public boolean isChildOfGroup(final Long groupId) { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateDTO.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateDTO.java index 31ded2d52..5fd8b0066 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateDTO.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateDTO.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.floatingrates.data; import java.math.BigDecimal; import java.time.LocalDate; import java.util.Collection; +import org.apache.fineract.infrastructure.core.service.DateUtils; public class FloatingRateDTO { @@ -43,7 +44,7 @@ public class FloatingRateDTO { BigDecimal rate = null; for (FloatingRatePeriodData periodData : this.baseLendingRatePeriods) { final LocalDate periodFromDate = periodData.getFromDate(); - if (periodFromDate.isBefore(date) || periodFromDate.isEqual(date)) { + if (!DateUtils.isAfter(periodFromDate, date)) { rate = periodData.getInterestRate(); break; } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java index 2393d2962..3091f4513 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java @@ -89,9 +89,8 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom { final String name = command.stringValueOfParameterNamed("name"); final boolean isBaseLendingRate = command.parameterExists("isBaseLendingRate") - ? command.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate") - : false; - final boolean isActive = command.parameterExists("isActive") ? command.booleanPrimitiveValueOfParameterNamed("isActive") : true; + && command.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate"); + final boolean isActive = !command.parameterExists("isActive") || command.booleanPrimitiveValueOfParameterNamed("isActive"); final List floatingRatePeriods = getRatePeriods(command); return new FloatingRate(name, isBaseLendingRate, isActive, floatingRatePeriods); @@ -109,8 +108,7 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom { final LocalDate fromDate = helper.extractLocalDateNamed("fromDate", ratePeriod, new HashSet()); final BigDecimal interestRate = ratePeriodObject.get("interestRate").getAsBigDecimal(); final boolean isDifferentialToBaseLendingRate = helper.parameterExists("isDifferentialToBaseLendingRate", ratePeriod) - ? ratePeriodObject.get("isDifferentialToBaseLendingRate").getAsBoolean() - : false; + && ratePeriodObject.get("isDifferentialToBaseLendingRate").getAsBoolean(); final boolean isActive = true; ratePeriods.add(new FloatingRatePeriod(fromDate, interestRate, isDifferentialToBaseLendingRate, isActive)); } @@ -170,7 +168,7 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom { if (this.floatingRatePeriods != null) { for (FloatingRatePeriod ratePeriod : this.floatingRatePeriods) { LocalDate fromDate = ratePeriod.getFromDate(); - if (fromDate.isAfter(today)) { + if (DateUtils.isAfter(fromDate, today)) { ratePeriod.setActive(false); } } @@ -188,7 +186,7 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom { for (FloatingRatePeriod floatingRatePeriod : this.floatingRatePeriods) { if (floatingRatePeriod.isActive()) { // will enter - if (applicableRates.isEmpty() && floatingRateDTO.getStartDate().isBefore(floatingRatePeriod.fetchFromDate())) { + if (applicableRates.isEmpty() && DateUtils.isBefore(floatingRateDTO.getStartDate(), floatingRatePeriod.fetchFromDate())) { if (floatingRateDTO.isFloatingInterestRate()) { addPeriodData = true; } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java index 6d12ced4e..a99fd76f4 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java @@ -340,7 +340,7 @@ public class GroupGeneralData implements Serializable { } public boolean isChildGroup() { - return this.centerId == null ? false : true; + return this.centerId != null; } public Long getParentId() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/StaffAssignmentHistory.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/StaffAssignmentHistory.java index 7e2874a16..373bfe103 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/StaffAssignmentHistory.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/StaffAssignmentHistory.java @@ -25,6 +25,7 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.time.LocalDate; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.staff.domain.Staff; @Entity @@ -73,7 +74,7 @@ public class StaffAssignmentHistory extends AbstractAuditableCustom { } public boolean matchesStartDateOf(final LocalDate matchingDate) { - return getStartDate().isEqual(matchingDate); + return DateUtils.isEqual(matchingDate, getStartDate()); } public LocalDate getStartDate() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java index 708edb187..b2ea0c9f1 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java @@ -27,6 +27,7 @@ import java.util.Map; import lombok.Getter; import org.apache.fineract.accounting.glaccount.data.GLAccountData; import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.infrastructure.core.service.DateUtils; @Getter public final class TaxComponentData implements Serializable { @@ -136,7 +137,7 @@ public final class TaxComponentData implements Serializable { } private boolean occursOnDayFrom(final LocalDate target) { - return target != null && target.isAfter(startDate()); + return DateUtils.isAfter(target, startDate()); } public LocalDate startDate() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java index 086f65d40..95adff636 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.tax.data; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; +import org.apache.fineract.infrastructure.core.service.DateUtils; public class TaxComponentHistoryData implements Serializable { @@ -38,10 +39,7 @@ public class TaxComponentHistoryData implements Serializable { } public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - if (this.endDate == null) { - return target != null && target.isAfter(startDate()); - } - return target != null && target.isAfter(startDate()) && !target.isAfter(endDate()); + return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); } public LocalDate startDate() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java index f0009cd8f..bc15a6670 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java @@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.tax.data; import java.io.Serializable; import java.time.LocalDate; +import org.apache.fineract.infrastructure.core.service.DateUtils; public class TaxGroupMappingsData implements Serializable { @@ -44,10 +45,7 @@ public class TaxGroupMappingsData implements Serializable { } public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - if (this.endDate == null) { - return target != null && target.isAfter(startDate()); - } - return target != null && target.isAfter(startDate()) && !target.isAfter(endDate()); + return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); } public LocalDate startDate() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java index dd12b3672..ac0d0a0ef 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java @@ -167,7 +167,7 @@ public class TaxComponent extends AbstractAuditableCustom { } private boolean occursOnDayFrom(final LocalDate target) { - return target != null && target.isAfter(startDate()); + return DateUtils.isAfter(target, startDate()); } public Set getTaxComponentHistories() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java index 63dfb54ea..5330fa14c 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java @@ -24,6 +24,7 @@ import jakarta.persistence.Table; import java.math.BigDecimal; import java.time.LocalDate; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; @Entity @Table(name = "m_tax_component_history") @@ -62,10 +63,7 @@ public class TaxComponentHistory extends AbstractAuditableCustom { } public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - if (this.endDate == null) { - return target != null && target.isAfter(startDate()); - } - return target != null && target.isAfter(startDate()) && !target.isAfter(endDate()); + return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); } public BigDecimal getPercentage() { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java index e1d4ff49b..ff95a1abd 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.tax.api.TaxApiConstants; @Entity @@ -81,10 +82,7 @@ public class TaxGroupMappings extends AbstractAuditableCustom { } public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - if (this.endDate == null) { - return target != null && target.isAfter(startDate()); - } - return target != null && target.isAfter(startDate()) && !target.isAfter(endDate()); + return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); } public TaxComponent getTaxComponent() { diff --git a/fineract-core/src/main/java/org/apache/fineract/useradministration/service/AppUserConstants.java b/fineract-core/src/main/java/org/apache/fineract/useradministration/service/AppUserConstants.java index 0bb0ccae7..25fbeb265 100644 --- a/fineract-core/src/main/java/org/apache/fineract/useradministration/service/AppUserConstants.java +++ b/fineract-core/src/main/java/org/apache/fineract/useradministration/service/AppUserConstants.java @@ -30,4 +30,6 @@ public final class AppUserConstants { // TODO: Remove hard coding of system user name and make this a configurable parameter public static final String SYSTEM_USER_NAME = "system"; + public static final Long ADMIN_USER_ID = 1L; + public static final Long SYSTEM_USER_ID = 2L; } diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/accounting/journalentry/service/InvestorAccountingHelper.java b/fineract-investor/src/main/java/org/apache/fineract/investor/accounting/journalentry/service/InvestorAccountingHelper.java index 5ab1dd267..944e4744b 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/accounting/journalentry/service/InvestorAccountingHelper.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/accounting/journalentry/service/InvestorAccountingHelper.java @@ -37,6 +37,7 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioPr import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMapping; import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository; import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.office.domain.Office; import org.springframework.stereotype.Service; @@ -61,7 +62,7 @@ public class InvestorAccountingHelper { **/ GLClosure gLClosure = getLatestClosureByBranch(officeId); if (gLClosure != null) { - if (gLClosure.getClosingDate().isAfter(transactionDate) || gLClosure.getClosingDate().isEqual(transactionDate)) { + if (!DateUtils.isAfter(transactionDate, gLClosure.getClosingDate())) { throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, gLClosure.getClosingDate(), null, null); } diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java index a9a4d24d9..c4790b920 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java @@ -170,7 +170,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW throw new ExternalAssetOwnerInitiateTransferException( String.format("This loan cannot be bought back, effective transfer is not in right state: %s", effectiveTransfers.get(0).getStatus())); - } else if (settlementDate.isBefore(effectiveTransfers.get(0).getSettlementDate())) { + } else if (DateUtils.isBefore(settlementDate, effectiveTransfers.get(0).getSettlementDate())) { throw new ExternalAssetOwnerInitiateTransferException( String.format("This loan cannot be bought back, settlement date is earlier than effective transfer settlement date: %s", effectiveTransfers.get(0).getSettlementDate())); @@ -251,7 +251,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW } private void validateSettlementDate(LocalDate settlementDate) { - if (settlementDate.isBefore(ThreadLocalContextUtil.getBusinessDate())) { + if (DateUtils.isBeforeBusinessDate(settlementDate)) { throw new ExternalAssetOwnerInitiateTransferException("Settlement date cannot be in the past"); } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java index 8e66b973e..243426ddd 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java @@ -22,6 +22,7 @@ import java.math.BigDecimal; import java.time.LocalDate; import lombok.Getter; import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.service.DateUtils; /** * Immutable data object representing disbursement information. @@ -85,8 +86,7 @@ public final class DisbursementData implements Comparable { if (obj == null) { return -1; } - - return obj.expectedDisbursementDate.compareTo(this.expectedDisbursementDate); + return DateUtils.compare(obj.expectedDisbursementDate, this.expectedDisbursementDate); } public boolean isDueForDisbursement(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) { @@ -96,14 +96,11 @@ public final class DisbursementData implements Comparable { private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive, final LocalDate target) { - return target != null && target.isAfter(fromNotInclusive) && !target.isAfter(upToAndInclusive); + return DateUtils.isAfter(target, fromNotInclusive) && !DateUtils.isAfter(target, upToAndInclusive); } public BigDecimal getWaivedChargeAmount() { - if (this.waivedChargeAmount == null) { - return BigDecimal.ZERO; - } - return this.waivedChargeAmount; + return this.waivedChargeAmount == null ? BigDecimal.ZERO : this.waivedChargeAmount; } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTermVariationsData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTermVariationsData.java index d1b64b81e..7b9858f07 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTermVariationsData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTermVariationsData.java @@ -22,6 +22,7 @@ import java.math.BigDecimal; import java.time.LocalDate; import lombok.Getter; import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType; @Getter @@ -64,7 +65,7 @@ public class LoanTermVariationsData implements Comparable mappings) { Collection retainMappings = new ArrayList<>(); for (LoanTransactionToRepaymentScheduleMapping updatedrepaymentScheduleMapping : mappings) { @@ -963,6 +939,18 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom { return amount; } + public boolean isBefore(final LocalDate date) { + return DateUtils.isBefore(getTransactionDate(), date); + } + + public boolean isAfter(final LocalDate date) { + return DateUtils.isAfter(getTransactionDate(), date); + } + + public boolean isOn(final LocalDate date) { + return DateUtils.isEqual(getTransactionDate(), date); + } + // TODO missing hashCode(), equals(Object obj), but probably OK as long as // this is never stored in a Collection. } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionComparator.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionComparator.java index fb4a51098..ead9e19a6 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionComparator.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionComparator.java @@ -19,47 +19,40 @@ package org.apache.fineract.portfolio.loanaccount.domain; import java.util.Comparator; +import org.apache.fineract.infrastructure.core.service.DateUtils; /** * Sort loan transactions by transaction date, created date and transaction type placing */ public class LoanTransactionComparator implements Comparator { + public static final LoanTransactionComparator INSTANCE = new LoanTransactionComparator(); + @Override public int compare(final LoanTransaction o1, final LoanTransaction o2) { - int compareResult = 0; - final int comparsion = o1.getTransactionDate().compareTo(o2.getTransactionDate()); - /** - * For transactions bearing the same transaction date, we sort transactions based on created date (when - * available) after which sorting for waivers takes place - **/ - if (comparsion == 0) { - int comparisonBasedOnCreatedDate = 0; - if (o1.isIncomePosting() && o2.isNotIncomePosting()) { - compareResult = -1; - } else if (o1.isNotIncomePosting() && o2.isIncomePosting()) { - compareResult = 1; - } else { - compareResult = 0; - } - if (o1.getCreatedDateTime() != null && o2.getCreatedDateTime() != null) { - comparisonBasedOnCreatedDate = o1.getCreatedDateTime().compareTo(o2.getCreatedDateTime()); - } - // equal transaction dates - if (comparisonBasedOnCreatedDate == 0) { - if (o1.isWaiver() && o2.isNotWaiver()) { - compareResult = -1; - } else if (o1.isNotWaiver() && o2.isWaiver()) { - compareResult = 1; - } else { - compareResult = 0; - } - } - } else { - compareResult = comparsion; + int result = DateUtils.compare(o1.getTransactionDate(), o2.getTransactionDate()); + if (result != 0) { + return result; } - - return compareResult; + // For transactions bearing the same transaction date, we sort transactions based on created date (when + // available) after which sorting for waivers takes place + result = o1.getCreatedDate().isPresent() + ? (o2.getCreatedDate().isPresent() ? DateUtils.compare(o1.getCreatedDateTime(), o2.getCreatedDateTime()) : -1) + : (o2.getCreatedDate().isPresent() ? 1 : 0); + if (result != 0) { + return result; + } + // equal transaction dates + if (o1.isIncomePosting() != o2.isIncomePosting()) { + return o1.isIncomePosting() ? -1 : 1; + } + if (o1.isWaiver() != o2.isWaiver()) { + return o1.isWaiver() ? -1 : 1; + } + result = o1.getId() != null ? (o2.getId() != null ? Long.compare(o1.getId(), o2.getId()) : -1) : (o2.getId() != null ? 1 : 0); + if (result != 0) { + return result; + } + return 0; } - } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java index 2cef9f4a9..fc6b5c468 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java @@ -200,11 +200,7 @@ public final class LoanSchedulePeriodData { this.totalOutstandingForPeriod = this.feeChargesOutstanding; this.totalActualCostOfLoanForPeriod = this.feeChargesDue; this.totalInstallmentAmountForPeriod = null; - if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } + this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null; this.totalCredits = BigDecimal.ZERO; this.downPaymentPeriod = false; } @@ -263,12 +259,7 @@ public final class LoanSchedulePeriodData { this.totalOutstandingForPeriod = totalDueForPeriod; this.totalActualCostOfLoanForPeriod = interestDueOnPrincipalOutstanding.add(feeChargesDueForPeriod); this.totalInstallmentAmountForPeriod = totalInstallmentAmountForPeriod; - - if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } + this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null; this.totalCredits = BigDecimal.ZERO; this.downPaymentPeriod = false; } @@ -322,12 +313,7 @@ public final class LoanSchedulePeriodData { this.totalOutstandingForPeriod = totalDueForPeriod; this.totalActualCostOfLoanForPeriod = null; this.totalInstallmentAmountForPeriod = totalDueForPeriod; - - if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } + this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null; this.totalCredits = BigDecimal.ZERO; this.downPaymentPeriod = true; } @@ -396,12 +382,7 @@ public final class LoanSchedulePeriodData { this.totalOutstandingForPeriod = totalOutstanding; this.totalActualCostOfLoanForPeriod = totalActualCostOfLoanForPeriod; this.totalInstallmentAmountForPeriod = totalInstallmentAmountForPeriod; - - if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } + this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null; this.totalCredits = totalCredits; this.downPaymentPeriod = isDownPayment; } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java index 4ea52809d..e741b003d 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; +import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; import java.math.MathContext; import java.time.LocalDate; @@ -26,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @@ -716,7 +718,7 @@ public final class LoanApplicationTerms { // number of days from 'ideal disbursement' to final date LocalDate loanStartDate = getExpectedDisbursementDate(); - if (getInterestChargedFromDate() != null && loanStartDate.isBefore(getInterestChargedFromLocalDate())) { + if (DateUtils.isBefore(loanStartDate, getInterestChargedFromLocalDate())) { loanStartDate = getInterestChargedFromLocalDate(); } @@ -773,7 +775,7 @@ public final class LoanApplicationTerms { CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(getLoanTermPeriodFrequencyType()), this.holidayDetailDTO.getWorkingDays(), isSkipRepaymentOnFirstDayOfMonth, numberOfDays); } - if (!expectedStartDate.isEqual(startDate)) { + if (!DateUtils.isEqual(expectedStartDate, startDate)) { diffDays = Math.toIntExact(ChronoUnit.DAYS.between(startDate, expectedStartDate)); } if (numberOfMonths == 0) { @@ -1368,6 +1370,7 @@ public final class LoanApplicationTerms { return this.multiDisburseLoan; } + @NotNull public Money getMaxOutstandingBalance() { return Money.of(getCurrency(), this.maxOutstandingBalance); } @@ -1440,7 +1443,7 @@ public final class LoanApplicationTerms { int months = getPeriodsBetween(fromDate, toDate); fromDate = fromDate.plusMonths(months); - isSameAsRepaymentPeriod = fromDate.isEqual(toDate); + isSameAsRepaymentPeriod = DateUtils.isEqual(fromDate, toDate); } break; diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java index 2aa882c6f..dd3c32002 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java @@ -59,6 +59,7 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGL import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException; import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.event.business.domain.journalentry.LoanJournalEntryCreatedBusinessEvent; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; import org.apache.fineract.organisation.office.domain.Office; @@ -502,12 +503,9 @@ public class AccountingProcessorHelper { * @param transactionDate */ public void checkForBranchClosures(final GLClosure latestGLClosure, final LocalDate transactionDate) { - /** - * check if an accounting closure has happened for this branch after the transaction Date - **/ + // check if an accounting closure has happened for this branch after the transaction Date if (latestGLClosure != null) { - if (latestGLClosure.getClosingDate().isAfter(transactionDate) - || latestGLClosure.getClosingDate().compareTo(transactionDate) == 0 ? Boolean.TRUE : Boolean.FALSE) { + if (!DateUtils.isBefore(latestGLClosure.getClosingDate(), transactionDate)) { throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(), null, null); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryRunningBalanceUpdateServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryRunningBalanceUpdateServiceImpl.java index 0d7db6d92..9b669f2cb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryRunningBalanceUpdateServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryRunningBalanceUpdateServiceImpl.java @@ -175,8 +175,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap); params.add(new Object[] { Boolean.TRUE, runningBalance, officeRunningBalance, - platformSecurityContext.authenticatedUser().getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), - entryData.getId() }); + platformSecurityContext.authenticatedUser().getId(), DateUtils.getAuditOffsetDateTime(), entryData.getId() }); batchIndex++; if (batchIndex == batchUpdateSize || index == entryDataList.size() - 1) { this.jdbcTemplate.batchUpdate(sql, params); @@ -213,7 +212,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry for (JournalEntryData entryData : entryDataList) { BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap); params.add(new Object[] { runningBalance, platformSecurityContext.authenticatedUser().getId(), - DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), entryData.getId() }); + DateUtils.getAuditOffsetDateTime(), entryData.getId() }); } this.jdbcTemplate.batchUpdate(sql, params); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java index 97d09dcbf..4e9683950 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java @@ -314,9 +314,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa final LocalDate journalEntriesTransactionDate = journalEntries.get(0).getTransactionDate(); final GLClosure latestGLClosureByBranch = this.glClosureRepository.getLatestGLClosureByBranch(officeId); if (latestGLClosureByBranch != null) { - if (latestGLClosureByBranch.getClosingDate().isAfter(journalEntriesTransactionDate) - || latestGLClosureByBranch.getClosingDate().compareTo(journalEntriesTransactionDate) == 0 ? Boolean.TRUE - : Boolean.FALSE) { + if (!DateUtils.isBefore(latestGLClosureByBranch.getClosingDate(), journalEntriesTransactionDate)) { final String accountName = null; final String accountGLCode = null; throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, @@ -555,24 +553,22 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa } private void validateBusinessRulesForJournalEntries(final JournalEntryCommand command) { - /** check if date of Journal entry is valid ***/ + // check if date of Journal entry is valid final LocalDate transactionDate = command.getTransactionDate(); // shouldn't be in the future - final LocalDate todaysDate = DateUtils.getBusinessLocalDate(); - if (transactionDate.isAfter(todaysDate)) { + if (DateUtils.isDateInTheFuture(transactionDate)) { throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.FUTURE_DATE, transactionDate, null, null); } // shouldn't be before an accounting closure final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(command.getOfficeId()); if (latestGLClosure != null) { - if (latestGLClosure.getClosingDate().isAfter(transactionDate) - || latestGLClosure.getClosingDate().compareTo(transactionDate) == 0 ? Boolean.TRUE : Boolean.FALSE) { + if (!DateUtils.isBefore(latestGLClosure.getClosingDate(), transactionDate)) { throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(), null, null); } } - /*** check if credits and debits are valid **/ + // check if credits and debits are valid final SingleDebitOrCreditEntryCommand[] credits = command.getCredits(); final SingleDebitOrCreditEntryCommand[] debits = command.getDebits(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java index a12c72c05..fe723d2e9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java @@ -43,6 +43,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @@ -107,7 +108,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements private void validateForCreateJournalEntry(ProvisioningEntryData existingEntry, ProvisioningEntry requested) { LocalDate existingDate = existingEntry.getCreatedDate(); LocalDate requestedDate = requested.getCreatedDate(); - if (existingDate.isAfter(requestedDate) || existingDate.compareTo(requestedDate) == 0 ? Boolean.TRUE : Boolean.FALSE) { + if (!DateUtils.isBefore(existingDate, requestedDate)) { throw new ProvisioningJournalEntriesCannotbeCreatedException(existingEntry.getCreatedDate(), requestedDate); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java index ce151a272..45f77d9b9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java @@ -64,7 +64,7 @@ public class LoanAccountLock { public LoanAccountLock(Long loanId, LockOwner lockOwner, LocalDate lockPlacedOnCobBusinessDate) { this.loanId = loanId; this.lockOwner = lockOwner; - this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + this.lockPlacedOn = DateUtils.getAuditOffsetDateTime(); this.lockPlacedOnCobBusinessDate = lockPlacedOnCobBusinessDate; } @@ -75,6 +75,6 @@ public class LoanAccountLock { public void setNewLockOwner(LockOwner newLockOwner) { this.lockOwner = newLockOwner; - this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + this.lockPlacedOn = DateUtils.getAuditOffsetDateTime(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java index e01ffdc8e..4b405bf21 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java @@ -81,8 +81,8 @@ public class LoanCOBPartitioner implements Partitioner { } StopWatch sw = new StopWatch(); sw.start(); - List loanCOBPartitions = new ArrayList<>(retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays, - businessDate, isCatchUp != null ? isCatchUp : false, partitionSize)); + List loanCOBPartitions = new ArrayList<>( + retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays, businessDate, isCatchUp != null && isCatchUp, partitionSize)); sw.stop(); // if there is no loan to be closed, we still would like to create at least one partition diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java index 25c661ac2..3ac0a769f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java @@ -67,7 +67,7 @@ public class LoanLockingServiceImpl implements LoanLockingService { UPDATE m_loan_account_locks SET version= version + 1, lock_owner = ?, lock_placed_on = ? WHERE loan_id = ? """, accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> { ps.setString(1, lockOwner.name()); - ps.setObject(2, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision()); + ps.setObject(2, DateUtils.getAuditOffsetDateTime()); ps.setLong(3, id); }); } @@ -97,7 +97,7 @@ public class LoanLockingServiceImpl implements LoanLockingService { ps.setLong(1, loanId); ps.setLong(2, 1); ps.setString(3, lockOwner.name()); - ps.setObject(4, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision()); + ps.setObject(4, DateUtils.getAuditOffsetDateTime()); ps.setObject(5, cobBusinessDate); }); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java index fe53d3fd7..f8376f9b9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java @@ -32,6 +32,7 @@ import org.apache.fineract.cob.loan.RetrieveLoanIdService; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.core.config.TaskExecutorConstant; import org.apache.fineract.infrastructure.core.domain.FineractContext; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO; import org.apache.fineract.infrastructure.jobs.domain.JobParameterRepository; @@ -73,7 +74,7 @@ public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorServ LocalDate oldestCOBProcessedDate = !loanIdAndLastClosedBusinessDate.isEmpty() ? loanIdAndLastClosedBusinessDate.get(0).getLastClosedBusinessDate() : cobBusinessDate; - if (oldestCOBProcessedDate.isBefore(cobBusinessDate)) { + if (DateUtils.isBefore(oldestCOBProcessedDate, cobBusinessDate)) { executeLoanCOBDayByDayUntilCOBBusinessDate(oldestCOBProcessedDate, cobBusinessDate); } } catch (NoSuchJobException e) { @@ -92,7 +93,7 @@ public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorServ Job job = jobLocator.getJob(LoanCOBConstant.JOB_NAME); ScheduledJobDetail scheduledJobDetail = scheduledJobDetailRepository.findByJobName(LoanCOBConstant.JOB_HUMAN_READABLE_NAME); LocalDate executingBusinessDate = oldestCOBProcessedDate.plusDays(1); - while (!executingBusinessDate.isAfter(cobBusinessDate)) { + while (!DateUtils.isAfter(executingBusinessDate, cobBusinessDate)) { JobParameterDTO jobParameterDTO = new JobParameterDTO(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME, executingBusinessDate.format(DateTimeFormatter.ISO_DATE)); JobParameterDTO jobParameterCatchUpDTO = new JobParameterDTO(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME, "true"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java index 271e43a8d..b46831726 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java @@ -51,6 +51,7 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuild import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException; import org.apache.fineract.infrastructure.core.exception.PlatformRequestBodyItemLimitValidationException; import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO; import org.apache.fineract.infrastructure.jobs.domain.CustomJobParameterRepository; @@ -112,7 +113,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService loansToBeProcessed = getLoansToBeProcessed(loanIds, cobBusinessDate); LocalDate executingBusinessDate = getOldestCOBBusinessDate(loansToBeProcessed).plusDays(1); if (!loansToBeProcessed.isEmpty()) { - while (!executingBusinessDate.isAfter(cobBusinessDate)) { + while (!DateUtils.isAfter(executingBusinessDate, cobBusinessDate)) { execute(getLoanIdsToBeProcessed(loansToBeProcessed, executingBusinessDate), jobName, executingBusinessDate); executingBusinessDate = executingBusinessDate.plusDays(1); } @@ -123,7 +124,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService loanIdsToBeProcessed = new ArrayList<>(); loansToBeProcessed.forEach(loan -> { if (loan.getLastClosedBusinessDate() != null) { - if (loan.getLastClosedBusinessDate().isBefore(executingBusinessDate)) { + if (DateUtils.isBefore(loan.getLastClosedBusinessDate(), executingBusinessDate)) { loanIdsToBeProcessed.add(loan.getId()); } } else { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java index b8a00129d..139802962 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java @@ -73,7 +73,7 @@ public class ImportDocument extends AbstractPersistableCustom { final Boolean completed = Boolean.FALSE; final Integer successCount = 0; final Integer failureCount = 0; - final LocalDateTime endTime = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()); + final LocalDateTime endTime = DateUtils.getLocalDateTimeOfTenant(); return new ImportDocument(document, importTime, endTime, completed, entityType, createdBy, totalRecords, successCount, failureCount); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java index 5e0604c06..07c720d20 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java @@ -145,8 +145,7 @@ public final class ImportHandlerUtils { return null; } - LocalDate localDate = LocalDate.ofInstant(c.getDateCellValue().toInstant(), DateUtils.getDateTimeZoneOfTenant()); - return localDate; + return LocalDate.ofInstant(c.getDateCellValue().toInstant(), DateUtils.getDateTimeZoneOfTenant()); } public static Boolean readAsBoolean(int colIndex, Row row) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java index 5e207236a..2807875e7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java @@ -101,8 +101,7 @@ public class SharedProductsSheetPopulator extends AbstractWorkbookPopulator { if (marketDataSet != null && !marketDataSet.isEmpty()) { LocalDate currentDate = DateUtils.getBusinessLocalDate(); for (ShareProductMarketPriceData data : marketDataSet) { - LocalDate futureDate = data.getFromDate(); - if (currentDate.isAfter(futureDate)) { + if (DateUtils.isBefore(data.getFromDate(), currentDate)) { marketValue = data.getShareValue(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java index 408c3df3b..7af4a580d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java @@ -160,7 +160,7 @@ public class EmailCampaign extends AbstractPersistableCustom { final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); - LocalDateTime recurrenceStartDate = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()); + LocalDateTime recurrenceStartDate = DateUtils.getLocalDateTimeOfTenant(); if (EmailCampaignType.fromInt(campaignType.intValue()).isSchedule()) { if (command.hasParameter(EmailCampaignValidator.recurrenceStartDate)) { recurrenceStartDate = LocalDateTime.parse(command.stringValueOfParameterNamed(EmailCampaignValidator.recurrenceStartDate), @@ -178,7 +178,6 @@ public class EmailCampaign extends AbstractPersistableCustom { } public Map update(JsonCommand command) { - final Map actualChanges = new LinkedHashMap<>(5); if (command.isChangeInStringParameterNamed(EmailCampaignValidator.campaignName, this.campaignName)) { @@ -229,7 +228,6 @@ public class EmailCampaign extends AbstractPersistableCustom { } public void activate(final AppUser currentUser, final DateTimeFormatter formatter, final LocalDate activationLocalDate) { - if (isActive()) { // handle errors if already activated final String defaultUserMessage = "Cannot activate campaign. Campaign is already active."; @@ -271,14 +269,13 @@ public class EmailCampaign extends AbstractPersistableCustom { } public void reactivate(final AppUser currentUser, final DateTimeFormatter dateTimeFormat, final LocalDate reactivateLocalDate) { - if (!isClosed()) { // handle errors if already activated final String defaultUserMessage = "Cannot reactivate campaign. Campaign must be in closed state."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.must.be.closed", defaultUserMessage, EmailCampaignValidator.statusParamName, EmailCampaignStatus.fromInt(this.status).getCode()); - final List dataValidationErrors = new ArrayList(); + final List dataValidationErrors = new ArrayList<>(); dataValidationErrors.add(error); throw new PlatformApiDataValidationException(dataValidationErrors); @@ -352,55 +349,45 @@ public class EmailCampaign extends AbstractPersistableCustom { } private void validateActivationDate(final List dataValidationErrors) { - - if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) { - + if (getSubmittedOnDate() != null && DateUtils.isDateInTheFuture(getSubmittedOnDate())) { final String defaultUserMessage = "submitted date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future", defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - - if (getApprovedOnDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getApprovedOnDate())) { - + if (getApprovedOnDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getApprovedOnDate())) { final String defaultUserMessage = "submitted date cannot be after the activation date"; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date", defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - - if (getApprovedOnDate() != null && isDateInTheFuture(getApprovedOnDate())) { - + if (DateUtils.isDateInTheFuture(getApprovedOnDate())) { final String defaultUserMessage = "Activation date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future", defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate()); dataValidationErrors.add(error); } - } private void validateReactivationDate(final List dataValidationErrors) { - if (getApprovedOnDate() != null && isDateInTheFuture(getApprovedOnDate())) { - + if (DateUtils.isDateInTheFuture(getApprovedOnDate())) { final String defaultUserMessage = "Activation date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future", defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate()); dataValidationErrors.add(error); } - if (getApprovedOnDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getApprovedOnDate())) { - + if (getApprovedOnDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getApprovedOnDate())) { final String defaultUserMessage = "submitted date cannot be after the activation date"; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date", defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) { - + if (DateUtils.isDateInTheFuture(getSubmittedOnDate())) { final String defaultUserMessage = "submitted date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future", defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate); @@ -411,7 +398,7 @@ public class EmailCampaign extends AbstractPersistableCustom { } private void validateClosureDate(final List dataValidationErrors) { - if (getClosureDate() != null && isDateInTheFuture(getClosureDate())) { + if (getClosureDate() != null && DateUtils.isDateInTheFuture(getClosureDate())) { final String defaultUserMessage = "closure date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.closureDate.in.the.future", defaultUserMessage, EmailCampaignValidator.closureDateParamName, this.closureDate); @@ -419,9 +406,4 @@ public class EmailCampaign extends AbstractPersistableCustom { dataValidationErrors.add(error); } } - - private boolean isDateInTheFuture(final LocalDate localDate) { - return localDate.isAfter(DateUtils.getBusinessLocalDate()); - } - } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java index 6b7ca94f0..5759c335a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java @@ -31,7 +31,6 @@ import java.io.StringReader; import java.io.StringWriter; import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.util.ArrayList; @@ -56,11 +55,9 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.api.JsonQuery; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; -import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData; import org.apache.fineract.infrastructure.dataqueries.domain.Report; import org.apache.fineract.infrastructure.dataqueries.domain.ReportParameterUsage; @@ -98,7 +95,6 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai @Transactional @Override public CommandProcessingResult create(JsonCommand command) { - final AppUser currentUser = this.context.authenticatedUser(); this.emailCampaignValidator.validateCreate(command.json()); @@ -286,24 +282,21 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai if (emailCampaign.isDirect()) { insertDirectCampaignIntoEmailOutboundTable(emailCampaign.getParamValue(), emailCampaign.getEmailSubject(), emailCampaign.getEmailMessage(), emailCampaign.getCampaignName(), emailCampaign.getId()); - } else { - if (emailCampaign.isSchedule()) { - - /** - * if recurrence start date is in the future calculate next trigger date if not use recurrence start - * date us next trigger date when activating - */ - LocalDateTime nextTriggerDateWithTime; - if (emailCampaign.getRecurrenceStartDate().isBefore(tenantDateTime())) { - nextTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), - emailCampaign.getRecurrenceStartDate(), DateUtils.getLocalDateTimeOfTenant()); - } else { - nextTriggerDateWithTime = emailCampaign.getRecurrenceStartDate(); - } - - emailCampaign.setNextTriggerDate(nextTriggerDateWithTime); - this.emailCampaignRepository.saveAndFlush(emailCampaign); + } else if (emailCampaign.isSchedule()) { + // if recurrence start date is in the past, calculate next trigger date, otherwise use recurrence start + // date as next trigger date when activating + LocalDateTime nextTriggerDateWithTime; + LocalDateTime recurrenceStartDate = emailCampaign.getRecurrenceStartDate(); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); + if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) { + nextTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), recurrenceStartDate, + tenantDateTime); + } else { + nextTriggerDateWithTime = recurrenceStartDate; } + + emailCampaign.setNextTriggerDate(nextTriggerDateWithTime); + this.emailCampaignRepository.saveAndFlush(emailCampaign); } /* @@ -420,7 +413,6 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai @Transactional @Override public CommandProcessingResult reactivateEmailCampaign(final Long campaignId, JsonCommand command) { - this.emailCampaignValidator.validateActivation(command.json()); final AppUser currentUser = this.context.authenticatedUser(); @@ -433,23 +425,18 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai final LocalDate reactivationDate = command.localDateValueOfParameterNamed("activationDate"); emailCampaign.reactivate(currentUser, fmt, reactivationDate); if (emailCampaign.isSchedule()) { - - /** - * if recurrence start date is in the future calculate next trigger date if not use recurrence start date us - * next trigger date when activating - */ + // if recurrence start date is in the past, calculate next trigger date, otherwise use recurrence start date + // as next trigger date when activating LocalDateTime nextTriggerDate = null; - if (emailCampaign.getRecurrenceStartDate().isBefore(tenantDateTime())) { - nextTriggerDate = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), emailCampaign.getRecurrenceStartDate(), - DateUtils.getLocalDateTimeOfTenant()); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); + LocalDateTime recurrenceStartDate = emailCampaign.getRecurrenceStartDate(); + if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) { + nextTriggerDate = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), recurrenceStartDate, tenantDateTime); } else { - nextTriggerDate = emailCampaign.getRecurrenceStartDate(); + nextTriggerDate = recurrenceStartDate; } - // to get time of tenant - final LocalDateTime getTime = emailCampaign.getRecurrenceStartDate(); - - final String dateString = nextTriggerDate.toString() + " " + getTime.getHour() + ":" + getTime.getMinute() + ":" - + getTime.getSecond(); + final String dateString = nextTriggerDate.toString() + " " + recurrenceStartDate.getHour() + ":" + + recurrenceStartDate.getMinute() + ":" + recurrenceStartDate.getSecond(); final DateTimeFormatter simpleDateFormat = new DateTimeFormatterBuilder().parseCaseInsensitive().parseLenient() .appendPattern("yyyy-MM-dd HH:mm:ss").toFormatter(); final LocalDateTime nextTriggerDateWithTime = LocalDateTime.parse(dateString, simpleDateFormat); @@ -470,17 +457,4 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai throw new PlatformDataIntegrityException("error.msg.email.campaign.unknown.data.integrity.issue", "Unknown data integrity issue with resource: " + realCause.getMessage()); } - - private LocalDateTime tenantDateTime() { - LocalDateTime today = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()); - final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant(); - - if (tenant != null) { - final ZoneId zone = ZoneId.of(tenant.getTimezoneId()); - if (zone != null) { - today = LocalDateTime.now(zone); - } - } - return today; - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/TenantDateTimeUtil.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/TenantDateTimeUtil.java deleted file mode 100644 index 506709cdf..000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/TenantDateTimeUtil.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.infrastructure.campaigns.jobs; - -import java.time.LocalDateTime; -import java.time.ZoneId; -import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; -import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; - -public final class TenantDateTimeUtil { - - private TenantDateTimeUtil() {} - - public static LocalDateTime tenantDateTime() { - LocalDateTime today = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()); - final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant(); - - if (tenant != null) { - final ZoneId zone = ZoneId.of(tenant.getTimezoneId()); - today = LocalDateTime.now(zone); - } - return today; - } -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/executereportmailingjobs/ExecuteReportMailingJobsTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/executereportmailingjobs/ExecuteReportMailingJobsTasklet.java index df9e1d159..6a4e77ba8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/executereportmailingjobs/ExecuteReportMailingJobsTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/executereportmailingjobs/ExecuteReportMailingJobsTasklet.java @@ -80,7 +80,7 @@ public class ExecuteReportMailingJobsTasklet implements Tasklet { final LocalDateTime localDateTimeOftenant = DateUtils.getLocalDateTimeOfTenant(); final LocalDateTime nextRunDateTime = reportMailingJob.getNextRunDateTime(); - if (nextRunDateTime != null && nextRunDateTime.isBefore(localDateTimeOftenant)) { + if (nextRunDateTime != null && DateUtils.isBefore(nextRunDateTime, localDateTimeOftenant)) { final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat .newInstance(reportMailingJob.getEmailAttachmentFileFormat()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updateemailoutboundwithcampaignmessage/UpdateEmailOutboundWithCampaignMessageTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updateemailoutboundwithcampaignmessage/UpdateEmailOutboundWithCampaignMessageTasklet.java index 24c93c97a..4423454d1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updateemailoutboundwithcampaignmessage/UpdateEmailOutboundWithCampaignMessageTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updateemailoutboundwithcampaignmessage/UpdateEmailOutboundWithCampaignMessageTasklet.java @@ -43,7 +43,6 @@ import org.apache.fineract.infrastructure.campaigns.email.domain.EmailMessageRep import org.apache.fineract.infrastructure.campaigns.email.exception.EmailCampaignNotFound; import org.apache.fineract.infrastructure.campaigns.email.service.EmailCampaignReadPlatformService; import org.apache.fineract.infrastructure.campaigns.email.service.EmailCampaignWritePlatformService; -import org.apache.fineract.infrastructure.campaigns.jobs.TenantDateTimeUtil; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.calendar.service.CalendarUtils; import org.apache.fineract.portfolio.client.domain.Client; @@ -69,11 +68,11 @@ public class UpdateEmailOutboundWithCampaignMessageTasklet implements Tasklet { .retrieveAllScheduleActiveCampaign(); if (emailCampaignDataCollection != null) { for (EmailCampaignData emailCampaignData : emailCampaignDataCollection) { - LocalDateTime tenantDateNow = TenantDateTimeUtil.tenantDateTime(); + LocalDateTime tenantDateNow = DateUtils.getLocalDateTimeOfTenant(); LocalDateTime nextTriggerDate = emailCampaignData.getNextTriggerDate().toLocalDateTime(); log.debug("tenant time {} trigger time {}", tenantDateNow, nextTriggerDate); - if (nextTriggerDate.isBefore(tenantDateNow)) { + if (DateUtils.isBefore(nextTriggerDate, tenantDateNow)) { insertDirectCampaignIntoEmailOutboundTable(emailCampaignData.getParamValue(), emailCampaignData.getEmailSubject(), emailCampaignData.getEmailMessage(), emailCampaignData.getCampaignName(), emailCampaignData.getId()); updateTriggerDates(emailCampaignData.getId()); @@ -115,13 +114,12 @@ public class UpdateEmailOutboundWithCampaignMessageTasklet implements Tasklet { .orElseThrow(() -> new EmailCampaignNotFound(campaignId)); LocalDateTime nextTriggerDate = emailCampaign.getNextTriggerDate(); emailCampaign.setLastTriggerDate(nextTriggerDate); - LocalDateTime newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), - emailCampaign.getNextTriggerDate(), nextTriggerDate); - if (newTriggerDateWithTime.isBefore(DateUtils.getLocalDateTimeOfTenant())) { - newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), emailCampaign.getNextTriggerDate(), - DateUtils.getLocalDateTimeOfTenant()); + LocalDateTime newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), nextTriggerDate, + nextTriggerDate); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); + if (DateUtils.isBefore(newTriggerDateWithTime, tenantDateTime)) { + newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), nextTriggerDate, tenantDateTime); } - emailCampaign.setNextTriggerDate(newTriggerDateWithTime); emailCampaignRepository.saveAndFlush(emailCampaign); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updatesmsoutboundwithcampaignmessage/UpdateSmsOutboundWithCampaignMessageTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updatesmsoutboundwithcampaignmessage/UpdateSmsOutboundWithCampaignMessageTasklet.java index 6e430183d..e24a42fb7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updatesmsoutboundwithcampaignmessage/UpdateSmsOutboundWithCampaignMessageTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/jobs/updatesmsoutboundwithcampaignmessage/UpdateSmsOutboundWithCampaignMessageTasklet.java @@ -23,7 +23,6 @@ import java.util.Collection; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; -import org.apache.fineract.infrastructure.campaigns.jobs.TenantDateTimeUtil; import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignStatus; import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType; import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign; @@ -51,12 +50,12 @@ public class UpdateSmsOutboundWithCampaignMessageTasklet implements Tasklet { .findByTriggerTypeAndStatus(SmsCampaignTriggerType.SCHEDULE.getValue(), SmsCampaignStatus.ACTIVE.getValue()); if (!CollectionUtils.isEmpty(smsCampaignDataCollection)) { for (SmsCampaign smsCampaign : smsCampaignDataCollection) { - LocalDateTime tenantDateNow = TenantDateTimeUtil.tenantDateTime(); + LocalDateTime tenantDateNow = DateUtils.getLocalDateTimeOfTenant(); LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate(); log.debug("tenant time {} trigger time {} {}", tenantDateNow, nextTriggerDate, JobName.UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE.name()); - if (nextTriggerDate.isBefore(tenantDateNow)) { + if (DateUtils.isBefore(nextTriggerDate, tenantDateNow)) { smsCampaignWritePlatformService.insertDirectCampaignIntoSmsOutboundTable(smsCampaign); updateTriggerDates(smsCampaign.getId()); } @@ -70,11 +69,10 @@ public class UpdateSmsOutboundWithCampaignMessageTasklet implements Tasklet { .orElseThrow(() -> new SmsCampaignNotFound(campaignId)); LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate(); smsCampaign.setLastTriggerDate(nextTriggerDate); - LocalDateTime nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getNextTriggerDate(), - nextTriggerDate); - if (nextRuntime.isBefore(DateUtils.getLocalDateTimeOfTenant())) { - nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getNextTriggerDate(), - DateUtils.getLocalDateTimeOfTenant()); + LocalDateTime nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), nextTriggerDate, nextTriggerDate); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); + if (DateUtils.isBefore(nextRuntime, tenantDateTime)) { + nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), nextTriggerDate, tenantDateTime); } smsCampaign.setNextTriggerDate(nextRuntime); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AuditorAwareImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AuditorAwareImpl.java index 46ef34de1..981dd8aa9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AuditorAwareImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AuditorAwareImpl.java @@ -18,10 +18,10 @@ */ package org.apache.fineract.infrastructure.core.domain; +import static org.apache.fineract.useradministration.service.AppUserConstants.ADMIN_USER_ID; + import java.util.Optional; import org.apache.fineract.useradministration.domain.AppUser; -import org.apache.fineract.useradministration.domain.AppUserRepository; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.AuditorAware; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; @@ -29,9 +29,6 @@ import org.springframework.security.core.context.SecurityContextHolder; public class AuditorAwareImpl implements AuditorAware { - @Autowired - private AppUserRepository userRepository; - @Override public Optional getCurrentAuditor() { Optional currentUserId; @@ -50,6 +47,6 @@ public class AuditorAwareImpl implements AuditorAware { } private Optional retrieveSuperUser() { - return Optional.of(1L); + return Optional.of(ADMIN_USER_ID); // TODO change to SYSTEM_USER_ID and add rights } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java index 2a157c905..888a8d0a6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java @@ -420,7 +420,7 @@ public class ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl implemen LocalDate current = DateUtils.getLocalDateOfTenant(); LocalDate getExpiryDate = creditBureauToken.getExpires(); - if (getExpiryDate.isBefore(current)) { + if (DateUtils.isBefore(getExpiryDate, current)) { this.tokenRepositoryWrapper.delete(creditBureauToken); creditBureauToken = null; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/domain/FineractEntityToEntityMapping.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/domain/FineractEntityToEntityMapping.java index a3db3ef76..4ed6d7e61 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/domain/FineractEntityToEntityMapping.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/domain/FineractEntityToEntityMapping.java @@ -33,6 +33,7 @@ import lombok.Setter; import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.entityaccess.api.FineractEntityApiResourceConstants; import org.apache.fineract.infrastructure.entityaccess.exception.FineractEntityToEntityMappingDateException; @@ -69,7 +70,6 @@ public class FineractEntityToEntityMapping extends AbstractPersistableCustom { } public Map updateMap(final JsonCommand command) { - final Map actualChanges = new LinkedHashMap<>(9); if (command.isChangeInLongParameterNamed(FineractEntityApiResourceConstants.fromEnityType, this.fromId)) { @@ -95,10 +95,8 @@ public class FineractEntityToEntityMapping extends AbstractPersistableCustom { actualChanges.put(FineractEntityApiResourceConstants.endDate, valueAsInput); this.endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate); } - if (startDate != null && endDate != null) { - if (endDate.isBefore(startDate)) { - throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString()); - } + if (endDate != null && DateUtils.isBefore(endDate, startDate)) { + throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString()); } return actualChanges; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java index 75aced5d2..f83009e38 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java @@ -27,6 +27,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.entityaccess.api.FineractEntityApiResourceConstants; import org.apache.fineract.infrastructure.entityaccess.data.FineractEntityDataValidator; import org.apache.fineract.infrastructure.entityaccess.domain.FineractEntityAccess; @@ -86,9 +87,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces @Override @Transactional public CommandProcessingResult createEntityToEntityMapping(Long relId, JsonCommand command) { - try { - this.fromApiJsonDeserializer.validateForCreate(command.json()); final FineractEntityRelation mapId = this.fineractEntityRelationRepositoryWrapper.findOneWithNotFoundDetection(relId); @@ -99,10 +98,8 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces final LocalDate endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate); fromApiJsonDeserializer.checkForEntity(relId.toString(), fromId, toId); - if (startDate != null && endDate != null) { - if (endDate.isBefore(startDate)) { - throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString()); - } + if (endDate != null && DateUtils.isBefore(endDate, startDate)) { + throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString()); } final FineractEntityToEntityMapping newMap = FineractEntityToEntityMapping.newMap(mapId, fromId, toId, startDate, endDate); @@ -123,9 +120,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces @Override @Transactional public CommandProcessingResult updateEntityToEntityMapping(Long mapId, JsonCommand command) { - try { - this.fromApiJsonDeserializer.validateForUpdate(command.json()); final FineractEntityToEntityMapping mapForUpdate = this.fineractEntityToEntityMappingRepositoryWrapper diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java index 08f22b158..55b664e48 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java @@ -63,7 +63,7 @@ public class UpdateNpaTasklet implements Tasklet { resetNPASqlBuilder.append("set is_npa = false").append(", last_modified_by = ?, last_modified_on_utc = ? ").append(" FROM ") .append(fromPart).append(wherePart); } - jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision()); + jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), DateUtils.getAuditOffsetDateTime()); final StringBuilder updateSqlBuilder = new StringBuilder(900); @@ -82,8 +82,7 @@ public class UpdateNpaTasklet implements Tasklet { .append(fromPart).append(wherePart); } - final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(), - DateUtils.getOffsetDateTimeOfTenantWithMostPrecision()); + final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(), DateUtils.getAuditOffsetDateTime()); log.debug("{}: Records affected by updateNPA: {}", ThreadLocalContextUtil.getTenant().getName(), result); return RepeatStatus.FINISHED; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessToken.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessToken.java index 5290c93d2..5564fcbeb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessToken.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessToken.java @@ -67,19 +67,12 @@ public class TFAccessToken extends AbstractPersistableCustom { } public boolean isValid() { - return this.enabled && isDateInTheFuture(getValidTo()) && isDateInThePast(getValidFrom()); + // valid_from is in the past inclusive, valid_to is in the future exclusive + return this.enabled && !DateUtils.isAfterTenantDateTime(getValidFrom()) && DateUtils.isAfterTenantDateTime(getValidTo()); } public AccessTokenData toTokenData() { return new AccessTokenData().setToken(this.token).setValidFrom(getValidFrom().atZone(DateUtils.getDateTimeZoneOfTenant())) .setValidTo(getValidTo().atZone(DateUtils.getDateTimeZoneOfTenant())); } - - private boolean isDateInTheFuture(LocalDateTime dateTime) { - return dateTime.isAfter(DateUtils.getLocalDateTimeOfTenant()); - } - - private boolean isDateInThePast(LocalDateTime dateTime) { - return (dateTime.isBefore(DateUtils.getLocalDateTimeOfTenant()) || dateTime.isEqual(DateUtils.getLocalDateTimeOfTenant())); - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/SpringSecurityPlatformSecurityContext.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/SpringSecurityPlatformSecurityContext.java index 2c44e11da..4a8628d32 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/SpringSecurityPlatformSecurityContext.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/SpringSecurityPlatformSecurityContext.java @@ -157,7 +157,7 @@ public class SpringSecurityPlatformSecurityContext implements PlatformSecurityCo final LocalDate passwordExpirationDate = passWordLastUpdateDate.plusDays(passwordDurationDays); - if (DateUtils.getLocalDateOfTenant().isAfter(passwordExpirationDate)) { + if (DateUtils.isBeforeTenantDate(passwordExpirationDate)) { return true; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionsData.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionsData.java index 24a707d28..34c25ca7d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionsData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionsData.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction; @@ -41,7 +42,7 @@ public class InteropTransactionsData extends CommandProcessingResult { } List trans = account.getTransactions().stream().filter(filter).sorted((t1, t2) -> { - int i = t2.getDateOf().compareTo(t1.getDateOf()); + int i = DateUtils.compare(t2.getDateOf(), t1.getDateOf()); return i != 0 ? i : Long.signum(t2.getId() - t1.getId()); }).map(InteropTransactionData::build).collect(Collectors.toList()); return new InteropTransactionsData(account.getId(), trans); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java index c097d42c4..7c8d33798 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java @@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.organisation.holiday.api.HolidayApiConstants; import org.apache.fineract.organisation.holiday.data.HolidayDataValidator; @@ -206,18 +207,15 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit } private void validateInputDates(final LocalDate fromDate, final LocalDate toDate, final LocalDate repaymentsRescheduledTo) { - String defaultUserMessage = ""; - if (toDate.isBefore(fromDate)) { + if (DateUtils.isBefore(toDate, fromDate)) { defaultUserMessage = "To Date date cannot be before the From Date."; throw new HolidayDateException("to.date.cannot.be.before.from.date", defaultUserMessage, fromDate.toString(), toDate.toString()); } if (repaymentsRescheduledTo != null) { - if ((repaymentsRescheduledTo.isEqual(fromDate) || repaymentsRescheduledTo.isEqual(toDate) - || (repaymentsRescheduledTo.isAfter(fromDate) && repaymentsRescheduledTo.isBefore(toDate)))) { - + if (!DateUtils.isBefore(repaymentsRescheduledTo, fromDate) && !DateUtils.isAfter(repaymentsRescheduledTo, toDate)) { defaultUserMessage = "Repayments rescheduled date should be before from date or after to date."; throw new HolidayDateException("repayments.rescheduled.date.should.be.before.from.date.or.after.to.date", defaultUserMessage, repaymentsRescheduledTo.toString()); @@ -235,13 +233,12 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit // validate repaymentsRescheduledTo date // 1. should be within a 30 days date range. // 2. Alternative date should not be an exist holiday.//TBD - // 3. Holiday should not be on an repaymentsRescheduledTo date of - // another holiday.//TBD + // 3. Holiday should not be on an repaymentsRescheduledTo date of another holiday.//TBD - // restricting repaymentsRescheduledTo date to be within 30 days - // range - // before or after from date and to date. - if (repaymentsRescheduledTo.isBefore(fromDate.minusDays(30)) || repaymentsRescheduledTo.isAfter(toDate.plusDays(30))) { + // restricting repaymentsRescheduledTo date to be within 30 days range before or after from date and to + // date. + if (DateUtils.isBefore(repaymentsRescheduledTo, fromDate.minusDays(30)) + || DateUtils.isAfter(repaymentsRescheduledTo, toDate.plusDays(30))) { defaultUserMessage = "Repayments Rescheduled to date must be within 30 days before or after from and to dates"; throw new HolidayDateException("repayments.rescheduled.to.must.be.within.range", defaultUserMessage, fromDate.toString(), toDate.toString(), repaymentsRescheduledTo.toString()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java index 2305f7a58..dc500616d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java @@ -20,10 +20,10 @@ package org.apache.fineract.organisation.teller.data; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZonedDateTime; +import java.time.OffsetDateTime; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.organisation.teller.domain.Cashier; import org.apache.fineract.organisation.teller.domain.Teller; @@ -54,7 +54,6 @@ public class CashierTransactionDataValidator { } public void validateSettleCashAndCashOutTransactions(final Long cashierId, String currencyCode, final BigDecimal transactionAmount) { - final Integer offset = null; final Integer limit = null; final String orderBy = null; @@ -64,7 +63,7 @@ public class CashierTransactionDataValidator { final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder); final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.tellerManagementReadPlatformService .retrieveCashierTransactionsWithSummary(cashierId, false, fromDate, toDate, currencyCode, searchParameters); - if (cashierTxnWithSummary.getNetCash().subtract(transactionAmount).compareTo(BigDecimal.ZERO) < 0) { + if (MathUtil.isGreaterThan(transactionAmount, cashierTxnWithSummary.getNetCash())) { throw new CashierInsufficientAmountException(); } } @@ -81,16 +80,12 @@ public class CashierTransactionDataValidator { final LocalDate endDate = cashier.getEndDate(); final LocalDate tellerFromDate = teller.getStartDate(); final LocalDate tellerEndDate = teller.getEndDate(); - /** - * to validate cashier date range in range of teller date range - */ - if (fromDate.isBefore(tellerFromDate) || endDate.isBefore(tellerFromDate) - || (tellerEndDate != null && (fromDate.isAfter(tellerEndDate) || endDate.isAfter(tellerEndDate)))) { + // to validate cashier date range in range of teller date range + if (DateUtils.isBefore(fromDate, tellerFromDate) || DateUtils.isBefore(endDate, tellerFromDate) + || (tellerEndDate != null && (DateUtils.isAfter(fromDate, tellerEndDate) || DateUtils.isAfter(endDate, tellerEndDate)))) { throw new CashierDateRangeOutOfTellerDateRangeException(); } - /** - * to validate cashier has not been assigned for same duration - */ + // to validate cashier has not been assigned for same duration String sql = "select count(*) from m_cashiers c where c.staff_id = " + staffId + " AND " + "(('" + fromDate + "' BETWEEN c.start_date AND c.end_date OR '" + endDate + "' BETWEEN c.start_date AND c.end_date )" + " OR ( c.start_date BETWEEN '" + fromDate + "' AND '" + endDate + "' OR c.end_date BETWEEN '" + fromDate + "' AND '" @@ -98,8 +93,8 @@ public class CashierTransactionDataValidator { if (!cashier.getIsFullDay()) { String startTime = cashier.getStartTime(); String endTime = cashier.getEndTime(); - sql = sql + " AND ( Time(c.start_time) BETWEEN TIME(?) and TIME('" + endTime + "') or Time(c.end_time) BETWEEN TIME('" - + startTime + "') and TIME('" + endTime + "')) "; + sql = sql + " AND ( Time(c.start_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime + + "') or Time(c.end_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime + "')) "; } int count = this.jdbcTemplate.queryForObject(sql, Integer.class); // NOSONAR if (count > 0) { @@ -108,13 +103,13 @@ public class CashierTransactionDataValidator { } public void validateOnLoanDisbursal(AppUser user, String currencyCode, BigDecimal transactionAmount) { - LocalDateTime localDateTime = DateUtils.getLocalDateTimeOfTenant(); + LocalDate tenantDate = DateUtils.getLocalDateOfTenant(); + OffsetDateTime tenantDateTime = DateUtils.getOffsetDateTimeOfTenant(); if (user.getStaff() != null) { - String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND " - + " (case when c.full_day then '" + localDateTime.toLocalDate() + "' BETWEEN c.start_date AND c.end_date " + " else ('" - + localDateTime.toLocalDate() + "' BETWEEN c.start_date AND c.end_date and " + " TIME('" - + ZonedDateTime.of(localDateTime, DateUtils.getDateTimeZoneOfTenant()) - + "') BETWEEN TIME(c.start_time) AND TIME(c.end_time) ) end)"; + String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND (case when c.full_day then '" + + tenantDate + "' BETWEEN c.start_date AND c.end_date else ('" + tenantDate + + "' BETWEEN c.start_date AND c.end_date and TIME('" + tenantDateTime + + "') BETWEEN TIME(c.start_time) AND TIME(c.end_time)) end)"; try { Long cashierId = this.jdbcTemplate.queryForObject(sql, Long.class); // NOSONAR validateSettleCashAndCashOutTransactions(cashierId, currencyCode, transactionAmount); @@ -122,6 +117,5 @@ public class CashierTransactionDataValidator { LOG.error("Problem occurred in validateOnLoanDisbursal function", e); } } - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/serialization/TellerCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/serialization/TellerCommandFromApiJsonDeserializer.java index 0fccf5425..bf045239f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/serialization/TellerCommandFromApiJsonDeserializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/serialization/TellerCommandFromApiJsonDeserializer.java @@ -35,6 +35,7 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.teller.exception.InvalidDateInputException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -113,7 +114,7 @@ public final class TellerCommandFromApiJsonDeserializer { final String status = this.fromApiJsonHelper.extractStringNamed(STATUS, element); baseDataValidator.reset().parameter(STATUS).value(status).notBlank().notExceedingLengthOf(50); - if (endDate != null && endDate.isBefore(startDate)) { + if (endDate != null && DateUtils.isBefore(endDate, startDate)) { throw new InvalidDateInputException(startDate.toString(), endDate.toString()); } throwExceptionIfValidationWarningsExist(dataValidationErrors); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/jobs/executestandinginstructions/ExecuteStandingInstructionsTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/jobs/executestandinginstructions/ExecuteStandingInstructionsTasklet.java index 16fd0c3e1..888ba2d92 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/jobs/executestandinginstructions/ExecuteStandingInstructionsTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/jobs/executestandinginstructions/ExecuteStandingInstructionsTasklet.java @@ -75,12 +75,12 @@ public class ExecuteStandingInstructionsTasklet implements Tasklet { LocalDate startDate = data.validFrom(); if (frequencyType.isMonthly()) { startDate = startDate.withDayOfMonth(data.recurrenceOnDay()); - if (startDate.isBefore(data.validFrom())) { + if (DateUtils.isBefore(startDate, data.validFrom())) { startDate = startDate.plusMonths(1); } } else if (frequencyType.isYearly()) { startDate = startDate.withDayOfMonth(data.recurrenceOnDay()).withMonth(data.recurrenceOnMonth()); - if (startDate.isBefore(data.validFrom())) { + if (DateUtils.isBefore(startDate, data.validFrom())) { startDate = startDate.plusYears(1); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java index dd07013f3..ca2305c8d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java @@ -536,8 +536,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(fromLoanAccountId).getPaidInAdvance(); final boolean backdatedTxnsAllowedTill = false; - if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE - : Boolean.FALSE || transactionAmount.floatValue() > overpaid.floatValue()) { + if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 || transactionAmount.floatValue() > overpaid.floatValue()) { if (overpaid == null) { overpaid = BigDecimal.ZERO; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java index c731dc2fc..22bee0c55 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java @@ -279,7 +279,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ periodStartDate = fromDate; } else { final LocalDate currentDate = DateUtils.getLocalDateOfTenant(); - if (seedDate.isBefore(currentDate.minusYears(1))) { + if (DateUtils.isBefore(seedDate, currentDate.minusYears(1))) { periodStartDate = currentDate.minusYears(1); } else { periodStartDate = recurrenceStartDate; @@ -294,7 +294,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ if (tillDate != null) { if (endDate != null) { - if (endDate.isAfter(tillDate)) { + if (DateUtils.isAfter(endDate, tillDate)) { // to retrieve meeting dates tillspecified date (tillDate) periodEndDate = tillDate; } @@ -302,7 +302,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ // end date is null then fetch meeting dates tillDate periodEndDate = tillDate; } - } else if (endDate == null || endDate.isAfter(currentDate.plusYears(1))) { + } else if (endDate == null || DateUtils.isAfter(endDate, currentDate.plusYears(1))) { periodEndDate = currentDate.plusYears(1); } return periodEndDate; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/InternalClientInformationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/InternalClientInformationApiResource.java index e07c8f2d3..6c8f77000 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/InternalClientInformationApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/InternalClientInformationApiResource.java @@ -80,8 +80,8 @@ public class InternalClientInformationApiResource implements InitializingBean { final Client client = clientRepositoryWrapper.findOneWithNotFoundDetection(clientId); Map auditFields = new HashMap<>( - Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDate().orElse(null), LAST_MODIFIED_BY, - client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDate().orElse(null))); + Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDateTime(), LAST_MODIFIED_BY, + client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDateTime())); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializer.serialize(settings, auditFields); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientNonPerson.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientNonPerson.java index 77dc21e29..b4367a3bb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientNonPerson.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientNonPerson.java @@ -36,6 +36,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.client.api.ClientApiConstants; @Entity @@ -116,8 +117,7 @@ public class ClientNonPerson extends AbstractPersistableCustom { private void validateIncorpValidityTillDate(final Client client, final List dataValidationErrors) { if (getIncorpValidityTillLocalDate() != null && client.dateOfBirthLocalDate() != null - && client.dateOfBirthLocalDate().isAfter(getIncorpValidityTillLocalDate())) { - + && DateUtils.isAfter(client.dateOfBirthLocalDate(), getIncorpValidityTillLocalDate())) { final String defaultUserMessage = "incorpvaliditytill date cannot be after the incorporation date"; final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.incorpValidityTill.after.incorp.date", defaultUserMessage, ClientApiConstants.incorpValidityTillParamName, this.incorpValidityTill); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceImpl.java index baa51baa8..38684f1da 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceImpl.java @@ -99,9 +99,9 @@ public class ClientChargeWritePlatformServiceImpl implements ClientChargeWritePl final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME); - LocalDate activationDate = client.getActivationLocalDate(); + LocalDate activationDate = client.getActivationDate(); LocalDate dueDate = clientCharge.getDueLocalDate(); - if (dueDate.isBefore(activationDate)) { + if (DateUtils.isBefore(dueDate, activationDate)) { baseDataValidator.reset().parameter(ClientApiConstants.dueAsOfDateParamName).value(dueDate.format(fmt)) .failWithCodeNoParameterAddedToErrorCode("dueDate.before.activationDate"); @@ -275,7 +275,7 @@ public class ClientChargeWritePlatformServiceImpl implements ClientChargeWritePl if (requiresTransactionDateValidation) { validateTransactionDateOnWorkingDay(transactionDate, clientCharge, fmt); - if (client.getActivationLocalDate() != null && transactionDate.isBefore(client.getActivationLocalDate())) { + if (DateUtils.isBefore(transactionDate, client.getActivationDate())) { baseDataValidator.reset().parameter(ClientApiConstants.transactionDateParamName).value(transactionDate.format(fmt)) .failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate"); throw new PlatformApiDataValidationException(dataValidationErrors); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 9b8b4a7fd..3a1013a55 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -277,7 +277,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (command.hasParameter(ClientApiConstants.submittedOnDateParamName)) { submittedOnDate = command.localDateValueOfParameterNamed(ClientApiConstants.submittedOnDateParamName); } - if (active && submittedOnDate.isAfter(activationDate)) { + if (active && DateUtils.isAfter(submittedOnDate, activationDate)) { submittedOnDate = activationDate; } final Long savingsAccountId = null; @@ -743,7 +743,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP CommandProcessingResult commandProcessingResult = CommandProcessingResult.empty(); if (client.isActive() && client.savingsProductId() != null) { SavingsAccountDataDTO savingsAccountDataDTO = new SavingsAccountDataDTO(client, null, client.savingsProductId(), - client.getActivationLocalDate(), client.activatedBy(), fmt); + client.getActivationDate(), client.activatedBy(), fmt); commandProcessingResult = this.savingsApplicationProcessWritePlatformService.createActiveApplication(savingsAccountDataDTO); if (commandProcessingResult.getSavingsId() != null) { this.savingsRepositoryWrapper.findOneWithNotFoundDetection(commandProcessingResult.getSavingsId()); @@ -851,10 +851,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP throw new InvalidClientStateTransitionException("close", "is.under.transfer", errorMessage); } - if (client.isNotPending() && client.getActivationLocalDate() != null && client.getActivationLocalDate().isAfter(closureDate)) { + if (client.isNotPending() && DateUtils.isAfter(client.getActivationDate(), closureDate)) { final String errorMessage = "The client closureDate cannot be before the client ActivationDate."; throw new InvalidClientStateTransitionException("close", "date.cannot.before.client.actvation.date", errorMessage, - closureDate, client.getActivationLocalDate()); + closureDate, client.getActivationDate()); } final LegalForm legalForm = LegalForm.fromInt(client.getLegalForm()); entityDatatableChecksWritePlatformService.runTheCheck(clientId, EntityTables.CLIENT.getName(), StatusEnum.CLOSE.getCode(), @@ -866,7 +866,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (loanStatus.isOpen() || loanStatus.isPendingApproval() || loanStatus.isAwaitingDisbursal()) { final String errorMessage = "Client cannot be closed because of non-closed loans."; throw new InvalidClientStateTransitionException("close", "loan.non-closed", errorMessage); - } else if (loanStatus.isClosed() && loan.getClosedOnDate().isAfter(closureDate)) { + } else if (loanStatus.isClosed() && DateUtils.isAfter(loan.getClosedOnDate(), closureDate)) { final String errorMessage = "The client closureDate cannot be before the loan closedOnDate."; throw new InvalidClientStateTransitionException("close", "date.cannot.before.loan.closed.date", errorMessage, closureDate, loan.getClosedOnDate()); @@ -976,7 +976,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final String errorMessage = "Only clients pending activation may be withdrawn."; throw new InvalidClientStateTransitionException("rejection", "on.account.not.in.pending.activation.status", errorMessage, rejectionDate, client.getSubmittedOnDate()); - } else if (client.getSubmittedOnDate().isAfter(rejectionDate)) { + } else if (DateUtils.isAfter(client.getSubmittedOnDate(), rejectionDate)) { final String errorMessage = "The client rejection date cannot be before the client submitted date."; throw new InvalidClientStateTransitionException("rejection", "date.cannot.before.client.submitted.date", errorMessage, rejectionDate, client.getSubmittedOnDate()); @@ -1008,7 +1008,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final String errorMessage = "Only clients pending activation may be withdrawn."; throw new InvalidClientStateTransitionException("withdrawal", "on.account.not.in.pending.activation.status", errorMessage, withdrawalDate, client.getSubmittedOnDate()); - } else if (client.getSubmittedOnDate().isAfter(withdrawalDate)) { + } else if (DateUtils.isAfter(client.getSubmittedOnDate(), withdrawalDate)) { final String errorMessage = "The client withdrawal date cannot be before the client submitted date."; throw new InvalidClientStateTransitionException("withdrawal", "date.cannot.before.client.submitted.date", errorMessage, withdrawalDate, client.getSubmittedOnDate()); @@ -1034,7 +1034,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (!client.isClosed()) { final String errorMessage = "only closed clients may be reactivated."; throw new InvalidClientStateTransitionException("reactivation", "on.nonclosed.account", errorMessage); - } else if (client.getClosureDate().isAfter(reactivateDate)) { + } else if (DateUtils.isAfter(client.getClosureDate(), reactivateDate)) { final String errorMessage = "The client reactivation date cannot be before the client closed date."; throw new InvalidClientStateTransitionException("reactivation", "date.cannot.before.client.closed.date", errorMessage, reactivateDate, client.getClosureDate()); @@ -1060,7 +1060,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (!client.isRejected()) { final String errorMessage = "only rejected clients may be reactivated."; throw new InvalidClientStateTransitionException("undorejection", "on.nonrejected.account", errorMessage); - } else if (client.getRejectedDate().isAfter(undoRejectDate)) { + } else if (DateUtils.isAfter(client.getRejectedDate(), undoRejectDate)) { final String errorMessage = "The client reactivation date cannot be before the client rejected date."; throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.rejected.date", errorMessage, undoRejectDate, client.getRejectedDate()); @@ -1088,7 +1088,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (!client.isWithdrawn()) { final String errorMessage = "only withdrawal clients may be reactivated."; throw new InvalidClientStateTransitionException("undoWithdrawal", "on.nonwithdrawal.account", errorMessage); - } else if (client.getWithdrawalDate().isAfter(undoWithdrawalDate)) { + } else if (DateUtils.isAfter(client.getWithdrawalDate(), undoWithdrawalDate)) { final String errorMessage = "The client reactivation date cannot be before the client withdrawal date."; throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.withdrawal.date", errorMessage, undoWithdrawalDate, client.getWithdrawalDate()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java index 099e20b81..343eeabdb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java @@ -55,7 +55,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe // Get the oldest overdue installment if exists one for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) { if (!installment.isObligationsMet()) { - if (installment.getDueDate().isBefore(businessDate)) { + if (DateUtils.isBefore(installment.getDueDate(), businessDate)) { log.debug("Loan Id: {} with installment {} due date {}", loan.getId(), installment.getInstallmentNumber(), installment.getDueDate()); outstandingAmount = outstandingAmount.add(installment.getTotalOutstanding(loanCurrency).getAmount()); @@ -69,13 +69,13 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId()); for (LoanTransaction loanTransaction : chargebackTransactions) { - boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual( - installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate()); + boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = DateUtils + .isEqual(loanTransaction.getTransactionDate(), installment.getFromDate()) + || DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getFromDate()); boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment - && loanTransaction.getTransactionDate().isBefore(installment.getDueDate()); + && DateUtils.isBefore(loanTransaction.getTransactionDate(), installment.getDueDate()); boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment - && (loanTransaction.getTransactionDate().isEqual(installment.getDueDate()) - || loanTransaction.getTransactionDate().isBefore(installment.getDueDate())); + && !DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getDueDate()); if (isLoanTransactionIsOnOrAfterInstallmentFromDate && (isLoanTransactionIsBeforeNotLastInstallmentDueDate || isLoanTransactionIsOnOrBeforeLastInstallmentDueDate)) { amountAvailable = amountAvailable.subtract(loanTransaction.getAmount()); @@ -93,11 +93,12 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe amountAvailable = installment.getTotalPaid(loanCurrency).getAmount(); log.debug("Amount available {}", amountAvailable); for (LoanTransaction loanTransaction : chargebackTransactions) { - boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual( - installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate()); - boolean isLoanTransactionIsBeforeInstallmentDueDate = loanTransaction.getTransactionDate() - .isBefore(installment.getDueDate()); - boolean isLoanTransactionIsBeforeBusinessDate = loanTransaction.getTransactionDate().isBefore(businessDate); + boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = !DateUtils.isBefore(loanTransaction.getTransactionDate(), + installment.getFromDate()); + boolean isLoanTransactionIsBeforeInstallmentDueDate = DateUtils.isBefore(loanTransaction.getTransactionDate(), + installment.getDueDate()); + boolean isLoanTransactionIsBeforeBusinessDate = DateUtils.isBefore(loanTransaction.getTransactionDate(), + businessDate); if (isLoanTransactionIsOnOrAfterInstallmentFromDate && isLoanTransactionIsBeforeInstallmentDueDate && isLoanTransactionIsBeforeBusinessDate) { log.debug("Loan CB Transaction: {} {} {}", loanTransaction.getId(), loanTransaction.getTransactionDate(), diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java index e59d2e1f5..f7025e5b7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java @@ -153,7 +153,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group final boolean active = command.booleanPrimitiveValueOfParameterNamed(GroupingTypesApiConstants.activeParamName); LocalDate submittedOnDate = DateUtils.getBusinessLocalDate(); - if (active && submittedOnDate.isAfter(activationDate)) { + if (active && DateUtils.isAfter(submittedOnDate, activationDate)) { submittedOnDate = activationDate; } if (command.hasParameter(GroupingTypesApiConstants.submittedOnDateParamName)) { @@ -616,7 +616,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " cannot be closed because of non-closed loans."; throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed", errorMessage); - } else if (loanStatus.isClosed() && loan.getClosedOnDate().isAfter(closureDate)) { + } else if (loanStatus.isClosed() && DateUtils.isAfter(loan.getClosedOnDate(), closureDate)) { final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + "closureDate cannot be before the loan closedOnDate."; throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", @@ -640,7 +640,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group + " cannot be closed with active savings accounts associated."; throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "savings.account.not.closed", errorMessage); - } else if (saving.isClosed() && saving.getClosedOnDate().isAfter(closureDate)) { + } else if (saving.isClosed() && DateUtils.isAfter(saving.getClosedOnDate(), closureDate)) { final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " closureDate cannot be before the loan closedOnDate."; throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", @@ -906,7 +906,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group public void validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(final Office groupOffice, final GroupLevel groupLevel, final LocalDate activationDate) { - if (activationDate != null && groupOffice.getOpeningLocalDate().isAfter(activationDate)) { + if (activationDate != null && DateUtils.isAfter(groupOffice.getOpeningLocalDate(), activationDate)) { final String levelName = groupLevel.getLevelName(); final String errorMessage = levelName + " activation date should be greater than or equal to the parent Office's creation date " + activationDate.toString(); @@ -916,10 +916,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group } private void checkGroupMembersMeetingSyncWithCenterMeeting(final Long centerId, final Set groupMembers) { - - /** - * Get parent(center) calendar - */ + // Get parent(center) calendar Calendar ceneterCalendar = null; final CalendarInstance parentCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId( centerId, CalendarEntityType.CENTERS.getValue(), CalendarType.COLLECTION.getValue()); @@ -928,9 +925,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group } for (final Group group : groupMembers) { - /** - * Get child(group) calendar - */ + // Get child(group) calendar Calendar groupCalendar = null; final CalendarInstance groupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId( group.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue()); @@ -938,19 +933,14 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group groupCalendar = groupCalendarInstance.getCalendar(); } - /** - * Group shouldn't have a meeting when no meeting attached for center - */ + // Group shouldn't have a meeting when no meeting attached for center if (ceneterCalendar == null && groupCalendar != null) { throw new GeneralPlatformDomainRuleException( "error.msg.center.associating.group.not.allowed.with.meeting.attached.to.group", "Group with id " + group.getId() + " is already associated with meeting", group.getId()); } - /** - * Group meeting recurrence should match with center meeting recurrence - */ + // Group meeting recurrence should match with center meeting recurrence else if (ceneterCalendar != null && groupCalendar != null) { - if (!ceneterCalendar.getRecurrence().equalsIgnoreCase(groupCalendar.getRecurrence())) { throw new GeneralPlatformDomainRuleException("error.msg.center.associating.group.not.allowed.with.different.meeting", "Group with id " + group.getId() + " meeting recurrence doesnot matched with center meeting recurrence", diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java index f18083d29..6dd4d9ce8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Collection; import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.infrastructure.core.service.DateUtils; /** * Immutable data object representing a InterestRateChart. @@ -143,7 +144,7 @@ public final class InterestRateChartData { } public boolean isFromDateAfter(final LocalDate compareDate) { - return (compareDate == null) ? false : this.fromDate.isAfter(compareDate); + return compareDate != null && DateUtils.isAfter(this.fromDate, compareDate); } public LocalDate endDate() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java index 5c8e222ef..cd30a0544 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java @@ -47,6 +47,7 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -115,10 +116,8 @@ public class InterestRateChartDataValidator { isPrimaryGroupingByAmount = false; } - if (fromDate != null && toDate != null) { - if (fromDate.isAfter(toDate)) { - baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date"); - } + if (toDate != null && DateUtils.isAfter(fromDate, toDate)) { + baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date"); } // validate chart Slabs - mandatory when creating @@ -177,11 +176,8 @@ public class InterestRateChartDataValidator { if (isPrimaryGroupingByAmount == null) { isPrimaryGroupingByAmount = false; } - - if (fromDate != null && toDate != null) { - if (fromDate.isAfter(toDate)) { - baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date"); - } + if (toDate != null && DateUtils.isAfter(fromDate, toDate)) { + baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date"); } validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java index d6ee0237b..a1b7868d8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java @@ -312,10 +312,7 @@ public class InterestRateChartSlabFields { public boolean isBigDecimalSame(final BigDecimal obj1, final BigDecimal obj2) { if (obj1 == null || obj2 == null) { - if (Objects.compare(obj1, obj2, Comparator.nullsFirst(Comparator.naturalOrder())) == 0 ? Boolean.TRUE : Boolean.FALSE) { - return true; - } - return false; + return Objects.compare(obj1, obj2, Comparator.nullsFirst(Comparator.naturalOrder())) == 0; } return obj1.compareTo(obj2) == 0; } @@ -326,7 +323,7 @@ public class InterestRateChartSlabFields { } public boolean isAmountRangeProvided() { - return (this.amountRangeFrom == null) ? false : true; + return this.amountRangeFrom != null; } public BigDecimal annualInterestRate() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/InternalLoanInformationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/InternalLoanInformationApiResource.java index a3662c791..6e75fa02a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/InternalLoanInformationApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/InternalLoanInformationApiResource.java @@ -88,8 +88,8 @@ public class InternalLoanInformationApiResource implements InitializingBean { final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId); Map auditFields = new HashMap<>( - Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDate().orElse(null), LAST_MODIFIED_BY, - loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDate().orElse(null))); + Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDateTime(), LAST_MODIFIED_BY, + loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDateTime())); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializerForMap.serialize(settings, auditFields); } @@ -108,8 +108,8 @@ public class InternalLoanInformationApiResource implements InitializingBean { final LoanTransaction transaction = loanTransactionRepository.findById(transactionId).orElseThrow(); Map auditFields = new HashMap<>(Map.of(CREATED_BY, transaction.getCreatedBy().orElse(null), CREATED_DATE, - transaction.getCreatedDate().orElse(null), LAST_MODIFIED_BY, transaction.getLastModifiedBy().orElse(null), - LAST_MODIFIED_DATE, transaction.getLastModifiedDate().orElse(null))); + transaction.getCreatedDateTime(), LAST_MODIFIED_BY, transaction.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, + transaction.getLastModifiedDateTime())); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializerForMap.serialize(settings, auditFields); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 604e5804f..7b0416230 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -369,7 +369,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final Integer transactionType, Integer installmentNumber) { boolean isAccountTransfer = true; checkClientOrGroupActive(loan); - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loan.getId() + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -465,7 +465,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { boolean isAccountTransfer = true; final Loan loan = this.loanAccountAssembler.assembleFrom(accountId); checkClientOrGroupActive(loan); - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loan.getId() + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -518,7 +518,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId, final boolean isLoanToLoanTransfer) { final Loan loan = this.loanAccountAssembler.assembleFrom(loanId); checkClientOrGroupActive(loan); - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loan.getId() + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -551,7 +551,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { @Override public void reverseTransfer(final LoanTransaction loanTransaction) { if (loanTransaction.getLoan().isChargedOff() - && loanTransaction.getTransactionDate().isBefore(loanTransaction.getLoan().getChargedOffOnDate())) { + && DateUtils.isBefore(loanTransaction.getTransactionDate(), loanTransaction.getLoan().getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan transaction: " + loanTransaction.getId() + " reversal is not allowed before or on the date when the loan got charged-off", @@ -614,10 +614,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { Set loanCharges = loan.getActiveCharges(); for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getDueDate().isAfter(loan.getMaturityDate())) { + if (DateUtils.isAfter(installment.getDueDate(), loan.getMaturityDate())) { accruedTill = DateUtils.getBusinessLocalDate(); } - if (!isOrganisationDateEnabled || organisationStartDate.isBefore(installment.getDueDate())) { + if (!isOrganisationDateEnabled || DateUtils.isBefore(organisationStartDate, installment.getDueDate())) { generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualList, loanId, officeId, accrualStartDate, repaymentFrequency, repayEvery, interestCalculatedFrom, loanProductId, currency, currencyData, loanCharges, installment); @@ -641,12 +641,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final LocalDate interestCalculatedFrom, final Long loanProductId, final MonetaryCurrency currency, final CurrencyData currencyData, final Set loanCharges, final LoanRepaymentScheduleInstallment installment) { - if (!accruedTill.isBefore(installment.getDueDate()) - || (accruedTill.isAfter(installment.getFromDate()) && !accruedTill.isAfter(installment.getDueDate()))) { + if (!DateUtils.isBefore(accruedTill, installment.getDueDate()) || (DateUtils.isAfter(accruedTill, installment.getFromDate()) + && !DateUtils.isAfter(accruedTill, installment.getDueDate()))) { BigDecimal dueDateFeeIncome = BigDecimal.ZERO; BigDecimal dueDatePenaltyIncome = BigDecimal.ZERO; LocalDate chargesTillDate = installment.getDueDate(); - if (!accruedTill.isAfter(installment.getDueDate())) { + if (!DateUtils.isAfter(accruedTill, installment.getDueDate())) { chargesTillDate = accruedTill; } @@ -685,7 +685,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { @Override public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount, final String noteText, final ExternalId externalId, PaymentDetail paymentDetail) { - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loan.getId() + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -729,7 +729,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final List existingReversedTransactionIds = new ArrayList<>(); final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount); - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loan.getId() + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -768,7 +768,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { @Override public LoanTransaction foreCloseLoan(Loan loan, final LocalDate foreClosureDate, final String noteText, final ExternalId externalId, Map changes) { - if (loan.isChargedOff() && foreClosureDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(foreClosureDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loan.getId() + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -785,7 +785,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final ScheduleGeneratorDTO scheduleGeneratorDTO = null; final LoanRepaymentScheduleInstallment foreCloseDetail = loan.fetchLoanForeclosureDetail(foreClosureDate); if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct() - && (loan.getAccruedTill() == null || !foreClosureDate.isEqual(loan.getAccruedTill()))) { + && (loan.getAccruedTill() == null || !DateUtils.isEqual(foreClosureDate, loan.getAccruedTill()))) { loan.reverseAccrualsAfter(foreClosureDate); Money[] accruedReceivables = loan.getReceivableIncome(foreClosureDate); Money interestPortion = foreCloseDetail.getInterestCharged(currency).minus(accruedReceivables[0]); @@ -805,7 +805,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { loan.addLoanTransaction(accrualTransaction); Set accrualCharges = accrualTransaction.getLoanChargesPaid(); for (LoanCharge loanCharge : loan.getActiveCharges()) { - boolean isDue = fromDate.isEqual(loan.getDisbursementDate()) + boolean isDue = DateUtils.isEqual(fromDate, loan.getDisbursementDate()) ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, foreClosureDate) : loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate); if (loanCharge.isActive() && !loanCharge.isPaid() && (isDue || loanCharge.isInstalmentFee())) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentDataComparator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentDataComparator.java deleted file mode 100644 index 912366360..000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentDataComparator.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.portfolio.loanaccount.domain; - -import java.util.Comparator; -import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData; - -public class LoanRepaymentDataComparator implements Comparator { - - @Override - public int compare(final LoanTransactionData o1, final LoanTransactionData o2) { - return o2.getDate().compareTo(o1.getDate()); - } -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariationsComparator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariationsComparator.java index 8f7b3b5d7..95d4d09d4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariationsComparator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariationsComparator.java @@ -29,10 +29,8 @@ public class LoanTermVariationsComparator implements Comparator installments, final LocalDate transactionDate) { final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex); - return transactionDate.isBefore(currentInstallment.getDueDate()); + return DateUtils.isBefore(transactionDate, currentInstallment.getDueDate()); } /** @@ -325,7 +326,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen protected boolean isTransactionALateRepaymentOnInstallment(final int installmentIndex, final List installments, final LocalDate transactionDate) { final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex); - return transactionDate.isAfter(currentInstallment.getDueDate()); + return DateUtils.isAfter(transactionDate, currentInstallment.getDueDate()); } private void recalculateChargeOffTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction, @@ -477,7 +478,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen LocalDate pastDueDate = null; for (final LoanRepaymentScheduleInstallment currentInstallment : installments) { pastDueDate = currentInstallment.getDueDate(); - if (!currentInstallment.isAdditional() && currentInstallment.getDueDate().isAfter(transactionDate)) { + if (!currentInstallment.isAdditional() && DateUtils.isAfter(currentInstallment.getDueDate(), transactionDate)) { currentInstallment.addToCredits(transactionAmount.getAmount()); currentInstallment.addToPrincipal(transactionDate, transactionAmount); if (repaidAmount.isGreaterThanZero()) { @@ -491,7 +492,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen // If already exists an additional installment just update the due date and // principal from the Loan chargeback / CBR transaction } else if (currentInstallment.isAdditional()) { - if (transactionDate.isAfter(currentInstallment.getDueDate())) { + if (DateUtils.isAfter(transactionDate, currentInstallment.getDueDate())) { currentInstallment.updateDueDate(transactionDate); } @@ -669,18 +670,19 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen if (loanCharge.getAmountOutstanding(currency).isGreaterThanZero() && !loanCharge.isDueAtDisbursement()) { if (loanCharge.isInstalmentFee()) { LoanInstallmentCharge unpaidLoanChargePerInstallment = loanCharge.getUnpaidInstallmentLoanCharge(); - if (chargePerInstallment == null || chargePerInstallment.getRepaymentInstallment().getDueDate() - .isAfter(unpaidLoanChargePerInstallment.getRepaymentInstallment().getDueDate())) { + if (chargePerInstallment == null || DateUtils.isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate(), + unpaidLoanChargePerInstallment.getRepaymentInstallment().getDueDate())) { installemntCharge = loanCharge; chargePerInstallment = unpaidLoanChargePerInstallment; } - } else if (earliestUnpaidCharge == null || loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) { + } else if (earliestUnpaidCharge == null + || DateUtils.isBefore(loanCharge.getDueLocalDate(), earliestUnpaidCharge.getDueLocalDate())) { earliestUnpaidCharge = loanCharge; } } } - if (earliestUnpaidCharge == null || (chargePerInstallment != null - && earliestUnpaidCharge.getDueLocalDate().isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate()))) { + if (earliestUnpaidCharge == null || (chargePerInstallment != null && DateUtils.isAfter(earliestUnpaidCharge.getDueLocalDate(), + chargePerInstallment.getRepaymentInstallment().getDueDate()))) { earliestUnpaidCharge = installemntCharge; } @@ -791,20 +793,20 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen if (loanCharge.isInstalmentFee()) { LoanInstallmentCharge paidLoanChargePerInstallment = loanCharge .getLastPaidOrPartiallyPaidInstallmentLoanCharge(currency); - if (chargePerInstallment == null - || (paidLoanChargePerInstallment != null && chargePerInstallment.getRepaymentInstallment().getDueDate() - .isBefore(paidLoanChargePerInstallment.getRepaymentInstallment().getDueDate()))) { + if (chargePerInstallment == null || (paidLoanChargePerInstallment != null + && DateUtils.isBefore(chargePerInstallment.getRepaymentInstallment().getDueDate(), + paidLoanChargePerInstallment.getRepaymentInstallment().getDueDate()))) { installemntCharge = loanCharge; chargePerInstallment = paidLoanChargePerInstallment; } } else if (latestPaidCharge == null || (loanCharge.isPaidOrPartiallyPaid(currency) - && loanCharge.getDueLocalDate().isAfter(latestPaidCharge.getDueLocalDate()))) { + && DateUtils.isAfter(loanCharge.getDueLocalDate(), latestPaidCharge.getDueLocalDate()))) { latestPaidCharge = loanCharge; } } } if (latestPaidCharge == null || (chargePerInstallment != null - && latestPaidCharge.getDueLocalDate().isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate()))) { + && DateUtils.isAfter(latestPaidCharge.getDueLocalDate(), chargePerInstallment.getRepaymentInstallment().getDueDate()))) { latestPaidCharge = installemntCharge; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java index 72b46c601..76bfb0ca6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java @@ -194,7 +194,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep switch (paymentAllocationType.getDueType()) { case PAST_DUE -> { currentInstallment = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff) - .filter(e -> loanTransaction.getTransactionDate().isAfter(e.getDueDate())) + .filter(e -> loanTransaction.isAfter(e.getDueDate())) .min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null); if (currentInstallment != null) { LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping( @@ -206,7 +206,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep } case DUE -> { currentInstallment = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff) - .filter(e -> loanTransaction.getTransactionDate().isEqual(e.getDueDate())) + .filter(e -> loanTransaction.isOn(e.getDueDate())) .min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null); if (currentInstallment != null) { LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping( @@ -222,14 +222,14 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep List currentInstallments = new ArrayList<>(); if (FutureInstallmentAllocationRule.REAMORTIZATION.equals(futureInstallmentAllocationRule)) { currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff) - .filter(e -> loanTransaction.getTransactionDate().isBefore(e.getDueDate())).toList(); + .filter(e -> loanTransaction.isBefore(e.getDueDate())).toList(); } else if (FutureInstallmentAllocationRule.NEXT_INSTALLMENT.equals(futureInstallmentAllocationRule)) { currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff) - .filter(e -> loanTransaction.getTransactionDate().isBefore(e.getDueDate())) + .filter(e -> loanTransaction.isBefore(e.getDueDate())) .min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).stream().toList(); } else if (FutureInstallmentAllocationRule.LAST_INSTALLMENT.equals(futureInstallmentAllocationRule)) { currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff) - .filter(e -> loanTransaction.getTransactionDate().isBefore(e.getDueDate())) + .filter(e -> loanTransaction.isBefore(e.getDueDate())) .max(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).stream().toList(); } int numberOfInstallments = currentInstallments.size(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessor.java index 10f372708..2915ef9e4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessor.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im import java.time.LocalDate; import java.util.List; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; @@ -102,7 +103,7 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio List orderedLoanChargesByDueDate = charges.stream().filter(LoanCharge::isActive).filter(LoanCharge::isChargePending) .filter(loanCharge -> loanCharge.getEffectiveDueDate() == null - || !loanCharge.getEffectiveDueDate().isAfter(transactionDate)) + || !DateUtils.isAfter(loanCharge.getEffectiveDueDate(), transactionDate)) .sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList(); Money calculatedPenaltyCharge = Money.zero(currency); Money calculatedFeeCharge = Money.zero(currency); @@ -141,7 +142,7 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio feeChargesPortion = feeChargesPortion.add(subFeePortion); Money subInterestPortion; - if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) { + if (ignoreDueDateCheck || !DateUtils.isBefore(transactionDate, currentInstallment.getDueDate())) { subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining); transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion); interestPortion = interestPortion.add(subInterestPortion); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessor.java index 804d62b8b..09e8d649e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessor.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im import java.time.LocalDate; import java.util.List; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; @@ -102,7 +103,7 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio List orderedLoanChargesByDueDate = charges.stream().filter(LoanCharge::isActive).filter(LoanCharge::isChargePending) .filter(loanCharge -> loanCharge.getEffectiveDueDate() == null - || !loanCharge.getEffectiveDueDate().isAfter(transactionDate)) + || !DateUtils.isAfter(loanCharge.getEffectiveDueDate(), transactionDate)) .sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList(); Money calculatedPenaltyCharge = Money.zero(currency); Money calculatedFeeCharge = Money.zero(currency); @@ -129,13 +130,11 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio penaltyChargesPortion = penaltyChargesPortion.add(subPenaltyPortion); Money subInterestPortion; - if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) { + if (ignoreDueDateCheck || !DateUtils.isBefore(transactionDate, currentInstallment.getDueDate())) { subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining); transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion); interestPortion = interestPortion.add(subInterestPortion); - } - if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) { Money subPrincipalPortion = currentInstallment.payPrincipalComponent(transactionDate, transactionAmountRemaining); transactionAmountRemaining = transactionAmountRemaining.minus(subPrincipalPortion); principalPortion = principalPortion.add(subPrincipalPortion); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java index e94cee83a..3e86d3b1b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im import java.time.LocalDate; import java.util.List; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; @@ -85,9 +86,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst final LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex); lastInstallmentDueDate = previousInstallment.getDueDate(); - isInAdvance = !(transactionDate.isAfter(lastInstallmentDueDate) || transactionDate.isEqual(lastInstallmentDueDate)); - - return isInAdvance; + return DateUtils.isBefore(transactionDate, lastInstallmentDueDate); } /** diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java index 9987180b9..44642f513 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im import java.time.LocalDate; import java.util.List; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; @@ -174,14 +175,12 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe private LoanRepaymentScheduleInstallment nearestInstallment(final LocalDate transactionDate, final List installments) { - - LoanRepaymentScheduleInstallment nearest = installments.get(0); + LoanRepaymentScheduleInstallment nearest = installments.get(0); // installments must be sorted by dates for (final LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getDueDate().isBefore(transactionDate) || installment.getDueDate().isEqual(transactionDate)) { - nearest = installment; - } else if (installment.getDueDate().isAfter(transactionDate)) { + if (DateUtils.isBefore(transactionDate, installment.getDueDate())) { break; } + nearest = installment; } return nearest; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java index 21ee7b02b..0888fe95d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java @@ -327,7 +327,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService { if (loan.isApproved() && !loan.isDisbursed()) { final List transactions = new ArrayList<>(); for (final SavingsAccountTransaction transaction : savingsAccount.getTransactions()) { - if (!transaction.getTransactionDate().isAfter(loan.getApprovedOnDate())) { + if (!DateUtils.isAfter(transaction.getTransactionDate(), loan.getApprovedOnDate())) { transactions.add(transaction); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java index 1c055efd4..a62bc2406 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java @@ -187,7 +187,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto private void validateGuarantorSavingsAccountActivationDateWithLoanSubmittedOnDate(final Loan loan, final SavingsAccount savingsAccount) { - if (loan.getSubmittedOnDate().isBefore(savingsAccount.getActivationDate())) { + if (DateUtils.isBefore(loan.getSubmittedOnDate(), savingsAccount.getActivationDate())) { throw new GeneralPlatformDomainRuleException( "error.msg.guarantor.saving.account.activation.date.is.on.or.before.loan.submitted.on.date", "Guarantor saving account activation date [" + savingsAccount.getActivationDate() diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java index ca9108eae..cf77e23c6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java @@ -27,6 +27,7 @@ import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueHolidayBusinessEvent; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; import org.apache.fineract.organisation.holiday.domain.Holiday; @@ -120,16 +121,15 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet { // Loop through all loanRepayments List installments = loan.getRepaymentScheduleInstallments(); for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) { - final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate(); // update from date if it's not same as previous installment's due // date. - if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) { + if (!DateUtils.isEqual(tmpFromDate, loanRepaymentScheduleInstallment.getFromDate())) { loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate); } - if (oldDueDate.equals(holiday.getFromDate()) || oldDueDate.isAfter(holiday.getFromDate())) { + if (!DateUtils.isBefore(oldDueDate, holiday.getFromDate())) { // FIXME: AA do we need to apply non-working days. // Assuming holiday's repayment reschedule to date cannot be // created on a non-working day. @@ -146,7 +146,7 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet { LocalDate adjustedRescheduleToDate = null; final LocalDate rescheduleToDate = holiday.getToDate(); for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : loan.getRepaymentScheduleInstallments()) { - if (rescheduleToDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) { + if (DateUtils.isEqual(rescheduleToDate, loanRepaymentScheduleInstallment.getDueDate())) { adjustedRescheduleToDate = rescheduleToDate; break; } else { @@ -160,9 +160,9 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet { private LocalDate doStandardMonthlyCheck(LocalDate adjustedRescheduleToDate, LocalDate rescheduleToDate, LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) { // Standard Monthly Loan Holiday check - if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate()) - && rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) { - adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate(); + LocalDate dueDate = loanRepaymentScheduleInstallment.getDueDate(); + if (DateUtils.isAfter(rescheduleToDate, dueDate) && DateUtils.isBefore(rescheduleToDate, dueDate.plusDays(30))) { + adjustedRescheduleToDate = dueDate; } return adjustedRescheduleToDate; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/transferfeechargeforloans/TransferFeeChargeForLoansTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/transferfeechargeforloans/TransferFeeChargeForLoansTasklet.java index 66c03a401..a9bf92790 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/transferfeechargeforloans/TransferFeeChargeForLoansTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/transferfeechargeforloans/TransferFeeChargeForLoansTasklet.java @@ -64,7 +64,7 @@ public class TransferFeeChargeForLoansTasklet implements Tasklet { .retrieveInstallmentLoanCharges(chargeData.getId(), true); PortfolioAccountData portfolioAccountData = null; for (final LoanInstallmentChargeData installmentChargeData : chargePerInstallments) { - if (!installmentChargeData.getDueDate().isAfter(DateUtils.getBusinessLocalDate())) { + if (!DateUtils.isDateInTheFuture(installmentChargeData.getDueDate())) { if (portfolioAccountData == null) { portfolioAccountData = accountAssociationsReadPlatformService .retriveLoanLinkedAssociation(chargeData.getLoanId()); @@ -79,7 +79,7 @@ public class TransferFeeChargeForLoansTasklet implements Tasklet { transferFeeCharge(accountTransferDTO, errors); } } - } else if (chargeData.getDueDate() != null && !chargeData.getDueDate().isAfter(DateUtils.getBusinessLocalDate())) { + } else if (chargeData.getDueDate() != null && !DateUtils.isDateInTheFuture(chargeData.getDueDate())) { final PortfolioAccountData portfolioAccountData = accountAssociationsReadPlatformService .retriveLoanLinkedAssociation(chargeData.getLoanId()); final boolean isExceptionForBalanceCheck = false; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index d1633a7a4..f116b914b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -204,7 +204,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener applyLoanVariationsForPartialScheduleGenerate(loanApplicationTerms, scheduleParams, interestRates, interestRatesForInstallments); - if (!firstRepaymentdate.isAfter(scheduleParams.getActualRepaymentDate())) { + if (!DateUtils.isAfter(firstRepaymentdate, scheduleParams.getActualRepaymentDate())) { isFirstRepayment = false; } } @@ -243,7 +243,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener continue; } - if (scheduleParams.getPeriodStartDate().isAfter(scheduledDueDate)) { + if (DateUtils.isAfter(scheduleParams.getPeriodStartDate(), scheduledDueDate)) { throw new ScheduleDateException("Due date can't be before period start date", scheduledDueDate); } @@ -254,8 +254,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener // this block is to generate the schedule till the specified // date(used for calculating preclosure) boolean isCompletePeriod = true; - if (scheduleParams.getScheduleTillDate() != null && !scheduledDueDate.isBefore(scheduleParams.getScheduleTillDate())) { - if (!scheduledDueDate.isEqual(scheduleParams.getScheduleTillDate())) { + if (scheduleParams.getScheduleTillDate() != null + && !DateUtils.isBefore(scheduledDueDate, scheduleParams.getScheduleTillDate())) { + if (!DateUtils.isEqual(scheduledDueDate, scheduleParams.getScheduleTillDate())) { isCompletePeriod = false; } scheduledDueDate = scheduleParams.getScheduleTillDate(); @@ -420,7 +421,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener currentDate = scheduleParams.getScheduleTillDate(); } if (scheduleParams.applyInterestRecalculation() && scheduleParams.getLatePaymentMap().size() > 0 - && currentDate.isAfter(scheduleParams.getPeriodStartDate())) { + && DateUtils.isAfter(currentDate, scheduleParams.getPeriodStartDate())) { Money totalInterest = addInterestOnlyRepaymentScheduleForCurrentdate(mc, loanApplicationTerms, holidayDetailDTO, currency, periods, currentDate, loanRepaymentScheduleTransactionProcessor, transactions, loanCharges, scheduleParams); scheduleParams.addTotalCumulativeInterest(totalInterest); @@ -449,7 +450,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Map periodCompoundingDetails = compoundingDetails.get(loanScheduleModelPeriod.periodFromDate()); if (periodCompoundingDetails != null) { for (Map.Entry entry : periodCompoundingDetails.entrySet()) { - if (entry.getValue().isGreaterThanZero() && !entry.getKey().isAfter(loanScheduleModelPeriod.periodDueDate())) { + if (entry.getValue().isGreaterThanZero() + && !DateUtils.isAfter(entry.getKey(), loanScheduleModelPeriod.periodDueDate())) { LocalDate effectiveDate = entry.getKey(); if (loanApplicationTerms.allowCompoundingOnEod()) { effectiveDate = effectiveDate.minusDays(1); @@ -734,7 +736,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } boolean updateLatePaymentMap = false; final LocalDate transactionDate = detail.getTransactionDate(); - if (transactionDate.isBefore(scheduledDueDate)) { + if (DateUtils.isBefore(transactionDate, scheduledDueDate)) { if (scheduleParams.getLoanRepaymentScheduleTransactionProcessor() != null && scheduleParams .getLoanRepaymentScheduleTransactionProcessor().isInterestFirstRepaymentScheduleTransactionProcessor()) { if (detail.getTransaction().isWaiver()) { @@ -748,8 +750,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener processTransactions.clear(); currentTransactions.addAll(createCurrentTransactionList(detail)); - if (!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) || scheduleParams.isFirstPeriod()) { - + if (!DateUtils.isEqual(transactionDate, scheduleParams.getPeriodStartDate()) || scheduleParams.isFirstPeriod()) { int periodDays = Math.toIntExact(ChronoUnit.DAYS.between(scheduleParams.getPeriodStartDate(), transactionDate)); // calculates period start date for interest // calculation as per the configuration @@ -842,7 +843,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener if (loanApplicationTerms.getPreClosureInterestCalculationStrategy().calculateTillRestFrequencyEnabled()) { LocalDate applicableDate = getNextRestScheduleDate(transactionDate.minusDays(1), loanApplicationTerms, holidayDetailDTO); - checkForOutstanding = transactionDate.isEqual(applicableDate); + checkForOutstanding = DateUtils.isEqual(transactionDate, applicableDate); } // reduces actual outstanding balance @@ -878,7 +879,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } else if (scheduleParams.getLoanRepaymentScheduleTransactionProcessor() != null) { LocalDate applicableDate = getNextRestScheduleDate(transactionDate.minusDays(1), loanApplicationTerms, holidayDetailDTO); - if (applicableDate.isBefore(scheduledDueDate)) { + if (DateUtils.isBefore(applicableDate, scheduledDueDate)) { List currentTransactions = createCurrentTransactionList(detail); Money unprocessed = scheduleParams.getLoanRepaymentScheduleTransactionProcessor() .handleRepaymentSchedule(currentTransactions, currency, scheduleParams.getInstallments(), loanCharges); @@ -937,7 +938,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } } - if (arrears.isGreaterThanZero() && applicableDate.isBefore(lastRestDate)) { + if (arrears.isGreaterThanZero() && DateUtils.isBefore(applicableDate, lastRestDate)) { handleLatePayments(loanApplicationTerms, holidayDetailDTO, currency, scheduleParams, lastRestDate, detail); } } @@ -991,15 +992,15 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener final BigDecimal chargesDueAtTimeOfDisbursement, LoanScheduleParams scheduleParams, final Collection periods, final LocalDate scheduledDueDate) { for (Map.Entry disburseDetail : scheduleParams.getDisburseDetailMap().entrySet()) { - if (disburseDetail.getKey().isAfter(scheduleParams.getPeriodStartDate()) - && !disburseDetail.getKey().isAfter(scheduledDueDate)) { + if (DateUtils.isAfter(disburseDetail.getKey(), scheduleParams.getPeriodStartDate()) + && !DateUtils.isAfter(disburseDetail.getKey(), scheduledDueDate)) { // validation check for amount not exceeds specified max // amount as per the configuration - if (loanApplicationTerms.getMaxOutstandingBalance() != null && scheduleParams.getOutstandingBalance() - .plus(disburseDetail.getValue()).isGreaterThan(loanApplicationTerms.getMaxOutstandingBalance())) { - String errorMsg = "Outstanding balance must not exceed the amount: " + loanApplicationTerms.getMaxOutstandingBalance(); - throw new MultiDisbursementOutstandingAmoutException(errorMsg, - loanApplicationTerms.getMaxOutstandingBalance().getAmount(), disburseDetail.getValue()); + Money maxOutstandingBalance = loanApplicationTerms.getMaxOutstandingBalance(); + if (scheduleParams.getOutstandingBalance().plus(disburseDetail.getValue()).isGreaterThan(maxOutstandingBalance)) { + String errorMsg = "Outstanding balance must not exceed the amount: " + maxOutstandingBalance; + throw new MultiDisbursementOutstandingAmoutException(errorMsg, maxOutstandingBalance.getAmount(), + disburseDetail.getValue()); } // creates and add disbursement detail to the repayments @@ -1045,7 +1046,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener // due date changes should be applied only for that dueDate if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) { LoanTermVariationsData loanTermVariationsData = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation(); - if (loanTermVariationsData.getTermVariationApplicableFrom().isEqual(modifiedScheduledDueDate)) { + if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) { modifiedScheduledDueDate = loanTermVariationsData.getDateValue(); if (!loanTermVariationsData.isSpecificToInstallment()) { scheduleParams.setActualRepaymentDate(modifiedScheduledDueDate); @@ -1097,7 +1098,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener loanTermVariationsData.setProcessed(true); break; case DELETE_INSTALLMENT: - if (loanTermVariationsData.getTermVariationApplicableFrom().isEqual(modifiedScheduledDueDate)) { + if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) { skipPeriod = true; loanTermVariationsData.setProcessed(true); } @@ -1205,7 +1206,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener variationsData.add(loanTermVariationsData); break; case DELETE_INSTALLMENT: - if (loanTermVariationsData.getTermVariationApplicableFrom().isEqual(modifiedScheduledDueDate)) { + if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) { skipPeriod = true; variationsData.add(loanTermVariationsData); } @@ -1363,7 +1364,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Money outstanding = params.getOutstandingBalanceAsPerRest(); Money totalInterest = Money.zero(currency); Money totalCumulativeInterest = Money.zero(currency); - double interestCalculationGraceOnRepaymentPeriodFraction = Double.valueOf(0); + double interestCalculationGraceOnRepaymentPeriodFraction = 0; int periodNumberTemp = 1; LocalDate lastRestDate = getNextRestScheduleDate(currentDate.minusDays(1), loanApplicationTerms, holidayDetailDTO); Collection applicableVariations = loanApplicationTerms.getLoanTermVariations().getInterestRateChanges(); @@ -1371,10 +1372,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener LocalDate additionalPeriodsStartDate = params.getPeriodStartDate(); do { - params.setActualRepaymentDate(this.scheduledDateGenerator.generateNextRepaymentDate(params.getActualRepaymentDate(), loanApplicationTerms, isFirstRepayment)); - if (params.getActualRepaymentDate().isAfter(currentDate)) { + if (DateUtils.isAfter(params.getActualRepaymentDate(), currentDate)) { params.setActualRepaymentDate(currentDate); } @@ -1391,7 +1391,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener LocalDate transactionDate = detail.getTransactionDate(); List currentTransactions = createCurrentTransactionList(detail); - if (!params.getPeriodStartDate().isEqual(transactionDate)) { + if (!DateUtils.isEqual(transactionDate, params.getPeriodStartDate())) { PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod( this.paymentPeriodsInOneYearCalculator, interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(), totalInterest.zero(), totalInterest.zero(), totalInterest.zero(), outstanding, loanApplicationTerms, @@ -1447,15 +1447,13 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Money uncompounded = params.getUnCompoundedAmount(); Money compounded = uncompounded.zero(); for (Map.Entry mapEntry : params.getCompoundingMap().entrySet()) { - if (mapEntry.getKey().isAfter(params.getPeriodStartDate())) { + if (DateUtils.isAfter(mapEntry.getKey(), params.getPeriodStartDate())) { compounded = compounded.plus(mapEntry.getValue()); } } - if (compounded.isGreaterThanZero() && startDate.isEqual(additionalPeriodsStartDate)) { - params.setCompoundedInLastInstallment(uncompoundedFromLastInstallment);// uncompounded - // in - // last - // installment + if (compounded.isGreaterThanZero() && DateUtils.isEqual(startDate, additionalPeriodsStartDate)) { + // uncompounded in last installment + params.setCompoundedInLastInstallment(uncompoundedFromLastInstallment); additionalPeriodsStartDate = additionalPeriodsStartDate.plusDays(1); } Money compoundedForThisPeriod = compounded.minus(uncompounded); @@ -1466,14 +1464,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener compoundingDate = compoundingDate.minusDays(1); } compoundingDate = getNextCompoundScheduleDate(compoundingDate, loanApplicationTerms, holidayDetailDTO); - if (compoundingDate.isEqual(params.getActualRepaymentDate())) { + if (DateUtils.isEqual(compoundingDate, params.getActualRepaymentDate())) { params.getCompoundingMap().put(compoundingDate, uncompoundedForThisPeriod); params.setUnCompoundedAmount(uncompoundedForThisPeriod.zero()); } } } params.setPeriodStartDate(params.getActualRepaymentDate()); - } while (params.getActualRepaymentDate().isBefore(currentDate) && !outstanding.isZero()); + } while (DateUtils.isBefore(params.getActualRepaymentDate(), currentDate) && !outstanding.isZero()); if (totalInterest.isGreaterThanZero()) { LoanScheduleModelRepaymentPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(params.getInstalmentNumber(), @@ -1503,7 +1501,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Collection applicableTransactions = new ArrayList<>(); if (applyInterestRecalculation && !Objects.isNull(transactions)) { for (RecalculationDetail detail : transactions) { - if (!detail.getTransactionDate().isAfter(repaymentDate)) { + if (!DateUtils.isBefore(repaymentDate, detail.getTransactionDate())) { applicableTransactions.add(detail); } } @@ -1574,7 +1572,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener List removeFromprincipalPortionMap = new ArrayList<>(); Money outstandingBalance = outstandingBalanceAsPerRest; for (Map.Entry principal : principalPortionMap.entrySet()) { - if (!principal.getKey().isAfter(scheduledDueDate)) { + if (!DateUtils.isAfter(principal.getKey(), scheduledDueDate)) { if (addMapDetails) { outstandingBalance = outstandingBalance.plus(principal.getValue()); } else { @@ -1610,11 +1608,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Money appliedOnPrincipalVariationMap = Money.zero(currency); Map temp = new HashMap<>(); for (LocalDate date : latePaymentCompoundingMap.keySet()) { - if (date.isBefore(lastRestDate)) { + if (DateUtils.isBefore(date, lastRestDate)) { Money money = latePaymentCompoundingMap.get(date); appliedOnPrincipalVariationMap = appliedOnPrincipalVariationMap.plus(money); if (appliedOnPrincipalVariationMap.isLessThan(compoundedPortion)) { - if (date.isBefore(applicableDate)) { + if (DateUtils.isBefore(date, applicableDate)) { updateMapWithAmount(principalVariationMap, money.negated(), date); updateMapWithAmount(principalVariationMap, money, applicableDate); } @@ -1648,14 +1646,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Money totalCompoundingAmount = Money.zero(currency); for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) { if (loanRepaymentScheduleInstallment.isNotFullyPaidOff() - && !loanRepaymentScheduleInstallment.getDueDate().isAfter(scheduledDueDate) + && !DateUtils.isAfter(loanRepaymentScheduleInstallment.getDueDate(), scheduledDueDate) && !loanRepaymentScheduleInstallment.isRecalculatedInterestComponent()) { LocalDate principalEffectiveDate = loanRepaymentScheduleInstallment.getDueDate(); if (applyRestFrequencyForPrincipal) { principalEffectiveDate = getNextRestScheduleDate(loanRepaymentScheduleInstallment.getDueDate().minusDays(1), loanApplicationTerms, holidayDetailDTO); } - if (principalEffectiveDate.isBefore(currentDate)) { + if (DateUtils.isBefore(principalEffectiveDate, currentDate)) { updateMapWithAmount(latePaymentMap, loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency), principalEffectiveDate); totalCompoundingAmount = totalCompoundingAmount @@ -1679,10 +1677,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : params.getInstallments()) { if (params.getCompoundingDateVariations().containsKey(loanRepaymentScheduleInstallment.getFromDate())) { lastInstallmentIsPastDate = params.applyInterestRecalculation() - && loanRepaymentScheduleInstallment.getDueDate().isBefore(DateUtils.getBusinessLocalDate()); + && DateUtils.isBeforeBusinessDate(loanRepaymentScheduleInstallment.getDueDate()); } else { final boolean isPastDate = params.applyInterestRecalculation() - && loanRepaymentScheduleInstallment.getDueDate().isBefore(DateUtils.getBusinessLocalDate()); + && DateUtils.isBeforeBusinessDate(loanRepaymentScheduleInstallment.getDueDate()); boolean periodHasCompoundingDate = false; Money amountCharged = Money.zero(currency); if (loanApplicationTerms.getInterestRecalculationCompoundingMethod() != null) { @@ -1697,7 +1695,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener holidayDetailDTO); final LocalDate restDate = getNextRestScheduleDate(scheduledDueDate.minusDays(1), loanApplicationTerms, holidayDetailDTO); - if (!compoundingEffectiveDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())) { + if (!DateUtils.isAfter(compoundingEffectiveDate, loanRepaymentScheduleInstallment.getDueDate())) { Money amountCompoundedFromLastPeriod = params.getCompoundedInLastInstallment(); if (amountCompoundedFromLastPeriod.isZero()) { amountCompoundedFromLastPeriod = params.getUnCompoundedAmount(); @@ -1705,12 +1703,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener totalCompoundedAmount = totalCompoundedAmount.minus(amountCompoundedFromLastPeriod); periodHasCompoundingDate = true; } - while (!compoundingEffectiveDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())) { - if (compoundingEffectiveDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) { + while (!DateUtils.isAfter(compoundingEffectiveDate, loanRepaymentScheduleInstallment.getDueDate())) { + if (DateUtils.isEqual(compoundingEffectiveDate, loanRepaymentScheduleInstallment.getDueDate())) { Money amountToBeCompounding = amountCharged.minus(totalCompoundedAmount); updateMapWithAmount(compoundingMap, amountToBeCompounding, compoundingEffectiveDate); totalCompoundedAmount = totalCompoundedAmount.plus(amountToBeCompounding); - } else if (compoundingMap.containsKey(compoundingEffectiveDate)) { Money compounedAmount = compoundingMap.get(compoundingEffectiveDate); totalCompoundedAmount = totalCompoundedAmount.plus(compounedAmount); @@ -1738,7 +1735,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener params.getCompoundingDateVariations().put(loanRepaymentScheduleInstallment.getFromDate(), new TreeMap<>(params.getCompoundingMap())); for (Map.Entry mapEntry : params.getCompoundingMap().entrySet()) { - if (!mapEntry.getKey().isAfter(loanRepaymentScheduleInstallment.getDueDate())) { + if (!DateUtils.isAfter(mapEntry.getKey(), loanRepaymentScheduleInstallment.getDueDate())) { updateMapWithAmount(params.getPrincipalPortionMap(), mapEntry.getValue().negated(), mapEntry.getKey()); } } @@ -1805,7 +1802,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener private void adjustCompoundedAmountWithPaidDetail(final Map principalPortionMap, final LocalDate lastRestDate, final LocalDate amountApplicableDate, final LoanTransaction transaction, final LoanApplicationTerms loanApplicationTerms, final MonetaryCurrency currency) { - if (!amountApplicableDate.isEqual(lastRestDate)) { + if (!DateUtils.isEqual(amountApplicableDate, lastRestDate)) { Money compoundedIncome = fetchCompoundedArrears(loanApplicationTerms, currency, transaction); updateMapWithAmount(principalPortionMap, compoundedIncome, amountApplicableDate); updateMapWithAmount(principalPortionMap, compoundedIncome.negated(), lastRestDate); @@ -1820,17 +1817,18 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener LocalDate lastCompoundingDate = startDate; LocalDate compoundingDate = startDate; boolean addUncompounded = true; - while (compoundingDate.isBefore(endDate)) { + while (DateUtils.isBefore(compoundingDate, endDate)) { if (loanApplicationTerms.allowCompoundingOnEod()) { compoundingDate = compoundingDate.minusDays(1); } compoundingDate = getNextCompoundScheduleDate(compoundingDate, loanApplicationTerms, holidayDetailDTO); - if (compoundingDate.isBefore(endDate)) { + if (DateUtils.isBefore(compoundingDate, endDate)) { + boolean isFirst = DateUtils.isEqual(startDate, lastCompoundingDate); Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(lastCompoundingDate, compoundingDate, charges, currency, - null, loanApplicationTerms.getPrincipal(), null, false, lastCompoundingDate.isEqual(startDate)); + null, loanApplicationTerms.getPrincipal(), null, false, isFirst); Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(lastCompoundingDate, compoundingDate, charges, - currency, null, loanApplicationTerms.getPrincipal(), null, false, lastCompoundingDate.isEqual(startDate)); + currency, null, loanApplicationTerms.getPrincipal(), null, false, isFirst); Money compoundAmount = feeChargesForInstallment.plus(penaltyChargesForInstallment); if (addUncompounded) { compoundAmount = compoundAmount.plus(scheduleParams.getUnCompoundedAmount()); @@ -1904,16 +1902,15 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate, final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled, final LocalDate expectedDisbursementDate) { LocalDate periodStartDateApplicableForInterest = periodStartDate; - if (periodStartDate.isBefore(idealDisbursementDate) || firstRepaymentdate.isAfter(periodStartDate)) { + if (DateUtils.isBefore(periodStartDate, idealDisbursementDate) || DateUtils.isBefore(periodStartDate, firstRepaymentdate)) { if (loanApplicationTerms.getInterestChargedFromLocalDate() != null) { - if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate()) - || loanApplicationTerms.getInterestChargedFromLocalDate().isAfter(periodStartDate)) { + if (DateUtils.isEqual(periodStartDate, loanApplicationTerms.getExpectedDisbursementDate()) + || DateUtils.isBefore(periodStartDate, loanApplicationTerms.getInterestChargedFromLocalDate())) { periodStartDateApplicableForInterest = loanApplicationTerms.getInterestChargedFromLocalDate(); } - } else if (loanApplicationTerms.getInterestChargedFromLocalDate() == null - && isInterestChargedFromDateSameAsDisbursalDateEnabled) { + } else if (isInterestChargedFromDateSameAsDisbursalDateEnabled) { periodStartDateApplicableForInterest = expectedDisbursementDate; - } else if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())) { + } else if (DateUtils.isEqual(periodStartDate, loanApplicationTerms.getExpectedDisbursementDate())) { periodStartDateApplicableForInterest = idealDisbursementDate; } } @@ -1969,7 +1966,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener if (disbursementData.disbursementDate().equals(disbursementDate)) { principal = principal.add(disbursementData.getPrincipal()); } else if (!excludePastUndisbursed || disbursementData.isDisbursed() - || !disbursementData.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) { + || !DateUtils.isBeforeBusinessDate(disbursementData.disbursementDate())) { /* * JW: sums up amounts by disbursal date in case of side-effect issues. Original assumed that there * were no duplicate disbursal dates and 'put' each amount into the map keyed by date @@ -2294,7 +2291,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener // this will generate the next schedule due date and allows to // process the installment only if recalculate from date is // greater than due date - if (installment.getDueDate().isAfter(lastInstallmentDate)) { + if (DateUtils.isAfter(installment.getDueDate(), lastInstallmentDate)) { if (totalCumulativePrincipal.isGreaterThanOrEqualTo(loanApplicationTerms.getTotalDisbursedAmount())) { break; } @@ -2305,7 +2302,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener do { actualRepaymentDate = this.scheduledDateGenerator.generateNextRepaymentDate(actualRepaymentDate, loanApplicationTerms, isFirstRepayment); - if (actualRepaymentDate.isAfter(rescheduleFrom) || actualRepaymentDate.isEqual(rescheduleFrom)) { + if (!DateUtils.isBefore(actualRepaymentDate, rescheduleFrom)) { actualRepaymentDate = lastInstallmentDate; } isFirstRepayment = false; @@ -2324,14 +2321,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } } - if (hasDueDateVariation && !lastInstallmentDate.isEqual(installment.getDueDate()) - && !installment.getDueDate().equals(modifiedLastInstDate)) { + if (hasDueDateVariation && !DateUtils.isEqual(lastInstallmentDate, installment.getDueDate()) + && !DateUtils.isEqual(modifiedLastInstDate, installment.getDueDate())) { lastInstallmentDate = prevLastInstDate; actualRepaymentDate = lastInstallmentDate; if (modifiedLastInstDate != null) { loanApplicationTerms.getLoanTermVariations().previousDueDateVariation(); } - } else if (installment.getDueDate().equals(modifiedLastInstDate)) { + } else if (DateUtils.isEqual(modifiedLastInstDate, installment.getDueDate())) { actualRepaymentDate = modifiedLastInstDate; lastInstallmentDate = actualRepaymentDate; dueDateVariationsDataList.add(variation1); @@ -2356,8 +2353,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } for (Map.Entry disburseDetail : disburseDetailMap.entrySet()) { - if (disburseDetail.getKey().isAfter(installment.getFromDate()) - && !disburseDetail.getKey().isAfter(installment.getDueDate())) { + if (DateUtils.isAfter(disburseDetail.getKey(), installment.getFromDate()) + && !DateUtils.isAfter(disburseDetail.getKey(), installment.getDueDate())) { // creates and add disbursement detail to the repayments // period final LoanScheduleModelDisbursementPeriod disbursementPeriod = LoanScheduleModelDisbursementPeriod @@ -2429,7 +2426,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener // recalculatedInterestComponent installment shouldn't be // considered while calculating fixed EMI amounts int period = periodNumber; - if (!lastInstallmentDate.isEqual(installment.getDueDate())) { + if (!DateUtils.isEqual(lastInstallmentDate, installment.getDueDate())) { period--; } reducePrincipal = fetchEarlyPaidAmount(installment.getPrincipal(currency), principalPortionCalculated, reducePrincipal, @@ -2513,7 +2510,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener int lastInterestAvilablePeriod = 0; int processedPeriod = 0; for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { - if (installment.getDueDate().isBefore(rescheduleFrom)) { + if (DateUtils.isBefore(installment.getDueDate(), rescheduleFrom)) { newRepaymentScheduleInstallments.add(installment); if (installment.getInterestCharged(currency).isGreaterThanZero()) { lastInterestAvilablePeriod = installment.getInstallmentNumber(); @@ -2614,7 +2611,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } compoundingDateVariations.put(installment.getFromDate(), compoundingMap); if (totalCompounded.isGreaterThanZero()) { - final boolean isPastDate = installment.getDueDate().isBefore(DateUtils.getBusinessLocalDate()); + final boolean isPastDate = DateUtils.isBeforeBusinessDate(installment.getDueDate()); final LocalDate restDate = getNextRestScheduleDate(installment.getDueDate().minusDays(1), loanApplicationTerms, holidayDetailDTO); if (isPastDate) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java index 3d00b33df..64b474f1f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java @@ -26,6 +26,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData; import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod; @@ -89,7 +90,7 @@ public class DecliningBalanceInterestLoanScheduleGenerator extends AbstractLoanS for (Map.Entry principal : principalVariation.entrySet()) { - if (!principal.getKey().isAfter(periodEndDate)) { + if (!DateUtils.isAfter(principal.getKey(), periodEndDate)) { int interestForDays = Math.toIntExact(ChronoUnit.DAYS.between(interestStartDate, principal.getKey())); if (interestForDays > 0) { final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java index 804cb1c40..6a646a3db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import net.fortuna.ical4j.model.Recur; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.holiday.domain.Holiday; import org.apache.fineract.organisation.holiday.service.HolidayUtil; import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO; @@ -92,7 +93,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { seedDate = currentCalendar.getStartDateLocalDate(); reccuringString = currentCalendar.getRecurrence(); } else { - seedDate = calendarHistory.getStartDateLocalDate(); + seedDate = calendarHistory.getStartDate(); reccuringString = calendarHistory.getRecurrence(); } @@ -177,7 +178,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { holidayDetailDTO.getHolidays())) != null) { if (applicableHolidayForNewAdjustedDate.getReScheduleType().isResheduleToNextRepaymentDate()) { LocalDate nextRepaymentPeriodDueDate = adjustedDateDetailsDTO.getChangedActualRepaymentDate(); - while (!nextRepaymentPeriodDueDate.isAfter(adjustedDateDetailsDTO.getChangedScheduleDate())) { + while (!DateUtils.isAfter(nextRepaymentPeriodDueDate, adjustedDateDetailsDTO.getChangedScheduleDate())) { nextRepaymentPeriodDueDate = generateNextRepaymentDate(nextRepaymentPeriodDueDate, loanApplicationTerms, isFirstRepayment); } @@ -208,14 +209,13 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { .getRepaymentRescheduleType(holidayDetailDTO.getWorkingDays()); if (repaymentRescheduleType.isMoveToNextRepaymentDay()) { - while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), - adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate()) - || adjustedDateDetailsDTO.getChangedScheduleDate() - .isAfter(adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate())) { - final LocalDate nextRepaymentPeriodDueDate = generateNextRepaymentDate( - adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate(), loanApplicationTerms, isFirstRepayment); - adjustedDateDetailsDTO.setNextRepaymentPeriodDueDate(nextRepaymentPeriodDueDate); + LocalDate nextRepaymentPeriodDueDate = adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate(); + while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), nextRepaymentPeriodDueDate) + || DateUtils.isAfter(adjustedDateDetailsDTO.getChangedScheduleDate(), nextRepaymentPeriodDueDate)) { + nextRepaymentPeriodDueDate = generateNextRepaymentDate(nextRepaymentPeriodDueDate, loanApplicationTerms, + isFirstRepayment); } + adjustedDateDetailsDTO.setNextRepaymentPeriodDueDate(nextRepaymentPeriodDueDate); } WorkingDaysUtil.updateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO.getWorkingDays()); } @@ -260,7 +260,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { isScheduledDate = (weekDiff % repaidEvery) == 0; if (isScheduledDate) { LocalDate modifiedDate = startDate.plusWeeks(weekDiff); - isScheduledDate = modifiedDate.isEqual(date); + isScheduledDate = DateUtils.isEqual(modifiedDate, date); } break; case MONTHS: @@ -268,7 +268,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { isScheduledDate = (monthDiff % repaidEvery) == 0; if (isScheduledDate) { LocalDate modifiedDate = startDate.plusMonths(monthDiff); - isScheduledDate = modifiedDate.isEqual(date); + isScheduledDate = DateUtils.isEqual(modifiedDate, date); } break; case YEARS: @@ -276,7 +276,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { isScheduledDate = (yearDiff % repaidEvery) == 0; if (isScheduledDate) { LocalDate modifiedDate = startDate.plusYears(yearDiff); - isScheduledDate = modifiedDate.isEqual(date); + isScheduledDate = DateUtils.isEqual(modifiedDate, date); } break; case INVALID: @@ -332,7 +332,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { LocalDate generatedDate = loanApplicationTerms.getExpectedDisbursementDate(); boolean isFirstRepayment = true; - while (!generatedDate.isAfter(lastRepaymentDate)) { + while (!DateUtils.isAfter(generatedDate, lastRepaymentDate)) { generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment); isFirstRepayment = false; } @@ -351,7 +351,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { isFirstRepayment = false; } LocalDate adjustedDate = generatedDate; - while (!adjustedDate.isAfter(lastRepaymentDate)) { + while (!DateUtils.isAfter(adjustedDate, lastRepaymentDate)) { generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment); adjustedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate(); isFirstRepayment = false; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java index f0e31f2ce..96b62325d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java @@ -431,7 +431,7 @@ public class LoanScheduleAssembler { LoanTermVariationsData loanTermVariation = new LoanTermVariationsData( LoanEnumerations.loanVariationType(LoanTermVariationType.INTEREST_RATE), periodData.getFromDateAsLocalDate(), periodData.getInterestRate(), dateValue, isSpecificToInstallment); - if (!interestRateStartDate.isBefore(periodData.getFromDateAsLocalDate())) { + if (!DateUtils.isBefore(interestRateStartDate, periodData.getFromDateAsLocalDate())) { interestRateStartDate = periodData.getFromDateAsLocalDate(); annualNominalInterestRate = periodData.getInterestRate(); } @@ -753,7 +753,7 @@ public class LoanScheduleAssembler { LocalDate lastDate = loan.getExpectedDisbursedOnLocalDate(); for (LoanRepaymentScheduleInstallment installment : installments) { dueDates.add(installment.getDueDate()); - if (lastDate.isBefore(installment.getDueDate())) { + if (DateUtils.isBefore(lastDate, installment.getDueDate())) { lastDate = installment.getDueDate(); } if (graceOnPrincipal.equals(installment.getInstallmentNumber())) { @@ -781,14 +781,14 @@ public class LoanScheduleAssembler { } else { dueDates.add(termVariations.fetchTermApplicaDate()); } - if (!graceApplicable.isBefore(termVariations.fetchTermApplicaDate())) { + if (!DateUtils.isBefore(graceApplicable, termVariations.fetchTermApplicaDate())) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.insert.not.allowed.before.grace.period", "Loan schedule insert request invalid"); } - if (termVariations.fetchTermApplicaDate().isAfter(lastDate)) { + if (DateUtils.isAfter(termVariations.fetchTermApplicaDate(), lastDate)) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.insert.not.allowed.after.last.period.date", "Loan schedule insert request invalid"); - } else if (termVariations.fetchTermApplicaDate().isBefore(loan.getExpectedDisbursedOnLocalDate())) { + } else if (DateUtils.isBefore(termVariations.fetchTermApplicaDate(), loan.getExpectedDisbursedOnLocalDate())) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.insert.not.allowed.before.disbursement.date", "Loan schedule insert request invalid"); } @@ -800,14 +800,13 @@ public class LoanScheduleAssembler { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("variable.schedule.remove.date.invalid", "Loan schedule remove request invalid"); } - if (termVariations.fetchTermApplicaDate().isEqual(lastDate)) { + if (DateUtils.isEqual(lastDate, termVariations.fetchTermApplicaDate())) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.delete.not.allowed.for.last.period.date", "Loan schedule remove request invalid"); } break; case DUE_DATE: if (dueDates.contains(termVariations.fetchTermApplicaDate())) { - if (overlappings.contains(termVariations.fetchTermApplicaDate())) { overlappings.remove(termVariations.fetchTermApplicaDate()); } else { @@ -822,17 +821,17 @@ public class LoanScheduleAssembler { } else { dueDates.add(termVariations.fetchDateValue()); } - if (termVariations.fetchDateValue().isBefore(loan.getExpectedDisbursedOnLocalDate())) { + if (DateUtils.isBefore(termVariations.fetchDateValue(), loan.getExpectedDisbursedOnLocalDate())) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.insert.not.allowed.before.disbursement.date", "Loan schedule insert request invalid"); } - if (termVariations.fetchTermApplicaDate().isEqual(lastDate)) { + if (DateUtils.isEqual(lastDate, termVariations.fetchTermApplicaDate())) { lastDate = termVariations.fetchDateValue(); } break; case PRINCIPAL_AMOUNT: case EMI_AMOUNT: - if (!graceApplicable.isBefore(termVariations.fetchTermApplicaDate())) { + if (!DateUtils.isBefore(graceApplicable, termVariations.fetchTermApplicaDate())) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.amount.update.not.allowed.before.grace.period", "Loan schedule modify request invalid"); } @@ -840,7 +839,7 @@ public class LoanScheduleAssembler { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.amount.update.from.date.invalid", "Loan schedule modify request invalid"); } - if (termVariations.fetchTermApplicaDate().isEqual(lastDate)) { + if (DateUtils.isEqual(termVariations.fetchTermApplicaDate(), lastDate)) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( "variable.schedule.amount.update.not.allowed.for.last.period", "Loan schedule modify request invalid"); } @@ -941,7 +940,7 @@ public class LoanScheduleAssembler { } if (dueDateVariations.containsKey(loanTermVariations.fetchTermApplicaDate())) { LoanTermVariations existingVariation = dueDateVariations.get(loanTermVariations.fetchTermApplicaDate()); - if (existingVariation.fetchTermApplicaDate().isEqual(loanTermVariations.fetchDateValue())) { + if (DateUtils.isEqual(existingVariation.fetchTermApplicaDate(), loanTermVariations.fetchDateValue())) { variations.remove(existingVariation); } else { existingVariation.setTermApplicableFrom(loanTermVariations.getDateValue()); @@ -1086,21 +1085,16 @@ public class LoanScheduleAssembler { final LocalDate expectedDisbursementDate, final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar, final LocalDate submittedOnDate, final RepaymentStartDateType repaymentStartDateType) { - LocalDate derivedFirstRepayment = null; final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = RepaymentStartDateType.DISBURSEMENT_DATE.equals( repaymentStartDateType) ? expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment) : submittedOnDate; if (calendar != null) { - - final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate; - derivedFirstRepayment = deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate, - refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType, - minimumDaysBetweenDisbursalAndFirstRepayment, calendar, submittedOnDate, repaymentStartDateType); - - } /*** Individual or group account, or JLG not linked to a meeting ***/ - else { + derivedFirstRepayment = deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate, expectedDisbursementDate, + repaymentPeriodFrequencyType, minimumDaysBetweenDisbursalAndFirstRepayment, calendar, submittedOnDate, + repaymentStartDateType); + } else { // Individual or group account, or JLG not linked to a meeting LocalDate dateBasedOnRepaymentFrequency; // Derive the first repayment date as greater date among // (disbursement date + plus frequency) or @@ -1121,16 +1115,15 @@ public class LoanScheduleAssembler { ? expectedDisbursementDate.plusMonths(repaymentEvery) : submittedOnDate.plusMonths(repaymentEvery); - } /** yearly loan **/ - else { + } else { // yearly loan dateBasedOnRepaymentFrequency = RepaymentStartDateType.DISBURSEMENT_DATE.equals(repaymentStartDateType) ? expectedDisbursementDate.plusYears(repaymentEvery) : submittedOnDate.plusYears(repaymentEvery); } - derivedFirstRepayment = dateBasedOnRepaymentFrequency.isAfter(dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment) - ? dateBasedOnRepaymentFrequency - : dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment; + derivedFirstRepayment = DateUtils.isAfter(dateBasedOnRepaymentFrequency, + dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment) ? dateBasedOnRepaymentFrequency + : dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment; } return derivedFirstRepayment; @@ -1148,7 +1141,7 @@ public class LoanScheduleAssembler { final LocalDate minimumFirstRepaymentDate = RepaymentStartDateType.DISBURSEMENT_DATE.equals(repaymentStartDateType) ? expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment) : submittedOnDate; - return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? derivedFirstRepayment + return DateUtils.isBefore(minimumFirstRepaymentDate, derivedFirstRepayment) ? derivedFirstRepayment : deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate, derivedFirstRepayment, repaymentPeriodFrequencyType, minimumDaysBetweenDisbursalAndFirstRepayment, calendar, submittedOnDate, repaymentStartDateType); @@ -1156,9 +1149,8 @@ public class LoanScheduleAssembler { private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDate disbursalDate, final LocalDate firstRepaymentDate, final Integer minimumDaysBetweenDisbursalAndFirstRepayment) { - final LocalDate minimumFirstRepaymentDate = disbursalDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment); - if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) { + if (DateUtils.isBefore(firstRepaymentDate, minimumFirstRepaymentDate)) { throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException(disbursalDate, firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java index 65d8206b5..6dba41379 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java @@ -168,7 +168,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC List installments = loan.getRepaymentScheduleInstallments(); for (final LoanRepaymentScheduleInstallment currentInstallment : installments) { if (currentInstallment.isNotFullyPaidOff()) { - if (!currentInstallment.getDueDate().isAfter(today)) { + if (!DateUtils.isAfter(currentInstallment.getDueDate(), today)) { totalPrincipal = totalPrincipal.plus(currentInstallment.getPrincipalOutstanding(currency)); } } @@ -190,7 +190,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC LoanScheduleData scheduleDate = model.toData(); Collection periodDatas = scheduleDate.getPeriods(); for (LoanSchedulePeriodData periodData : periodDatas) { - if ((periodData.getDueDate().isEqual(today) || periodData.getDueDate().isAfter(today)) && isNewPaymentRequired) { + if (isNewPaymentRequired && !DateUtils.isBefore(periodData.getDueDate(), today)) { LoanSchedulePeriodData loanSchedulePeriodData = LoanSchedulePeriodData.repaymentOnlyPeriod(periodData.getPeriod(), periodData.getFromDate(), periodData.getDueDate(), totalPrincipal.getAmount(), periodData.getPrincipalLoanBalanceOutstanding(), interestDue.getAmount(), @@ -199,7 +199,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC totalPrincipal.plus(interestDue).getAmount()); futureInstallments.add(loanSchedulePeriodData); isNewPaymentRequired = false; - } else if (periodData.getDueDate().isAfter(today)) { + } else if (DateUtils.isAfter(periodData.getDueDate(), today)) { futureInstallments.add(periodData); } @@ -239,7 +239,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC for (LoanRepaymentScheduleInstallment installment : installments) { if (loanDisbursementDetails != null - && !loanDisbursementDetails.expectedDisbursementDateAsLocalDate().isAfter(installment.getDueDate())) { + && !DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDateAsLocalDate(), installment.getDueDate())) { outstanding = outstanding.plus(loanDisbursementDetails.principal()); principal = principal.plus(loanDisbursementDetails.principal()); if (disbursementItr.hasNext()) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java index 9ed49e01e..d3628ae0c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java @@ -73,7 +73,7 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule final BigDecimal penaltyCharges = repaymentScheduleInstallment.getPenaltyChargesCharged(currency).getAmount(); Map oldDates = null; - OffsetDateTime createdOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + OffsetDateTime createdOnDate = DateUtils.getAuditOffsetDateTime(); LocalDateTime oldCreatedOnDate = null; LocalDateTime oldLastModifiedOnDate = null; if (repaymentScheduleInstallment.getCreatedDate().isPresent()) { @@ -89,7 +89,7 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule final Long lastModifiedByUser = repaymentScheduleInstallment.getLastModifiedBy() .orElse(platformSecurityContext.authenticatedUser().getId()); - OffsetDateTime lastModifiedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(); + OffsetDateTime lastModifiedOnDate = DateUtils.getAuditOffsetDateTime(); if (repaymentScheduleInstallment.getLastModifiedDate().isPresent()) { lastModifiedOnDate = repaymentScheduleInstallment.getLastModifiedDate().get(); } else if (repaymentScheduleInstallment.getId() != null && oldDates == null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java index 328d1ca2b..7f6f57abf 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java @@ -38,6 +38,7 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; @@ -105,7 +106,7 @@ public class LoanRescheduleRequestDataValidator { jsonElement); dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.submittedOnDateParamName).value(submittedOnDate).notNull(); - if (submittedOnDate != null && loan.getDisbursementDate().isAfter(submittedOnDate)) { + if (submittedOnDate != null && DateUtils.isAfter(loan.getDisbursementDate(), submittedOnDate)) { dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.submittedOnDateParamName) .failWithCode("before.loan.disbursement.date", "Submission date cannot be before the loan disbursement date"); } @@ -161,7 +162,7 @@ public class LoanRescheduleRequestDataValidator { final LocalDate adjustedDueDate = this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.adjustedDueDateParamName, jsonElement); - if (adjustedDueDate != null && rescheduleFromDate != null && adjustedDueDate.isBefore(rescheduleFromDate)) { + if (adjustedDueDate != null && DateUtils.isBefore(adjustedDueDate, rescheduleFromDate)) { dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName).failWithCode( "adjustedDueDate.before.rescheduleFromDate", "Adjusted due date cannot be before the reschedule from date"); } @@ -212,7 +213,7 @@ public class LoanRescheduleRequestDataValidator { LocalDate rescheduleFromDate = installment.getFromDate(); Collection charges = loan.getLoanCharges(); for (LoanCharge loanCharge : charges) { - if (loanCharge.isOverdueInstallmentCharge() && loanCharge.getDueLocalDate().isAfter(rescheduleFromDate)) { + if (loanCharge.isOverdueInstallmentCharge() && DateUtils.isAfter(loanCharge.getDueLocalDate(), rescheduleFromDate)) { dataValidatorBuilder.failWithCodeNoParameterAddedToErrorCode("not.allowed.due.to.overdue.charges"); break; } @@ -247,7 +248,7 @@ public class LoanRescheduleRequestDataValidator { jsonElement); dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.approvedOnDateParam).value(approvedOnDate).notNull(); - if (approvedOnDate != null && loanRescheduleRequest.getSubmittedOnDate().isAfter(approvedOnDate)) { + if (approvedOnDate != null && DateUtils.isAfter(loanRescheduleRequest.getSubmittedOnDate(), approvedOnDate)) { dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.approvedOnDateParam).failWithCode("before.submission.date", "Approval date cannot be before the request submission date."); } @@ -319,7 +320,7 @@ public class LoanRescheduleRequestDataValidator { jsonElement); dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rejectedOnDateParam).value(rejectedOnDate).notNull(); - if (rejectedOnDate != null && loanRescheduleRequest.getSubmittedOnDate().isAfter(rejectedOnDate)) { + if (rejectedOnDate != null && DateUtils.isAfter(loanRescheduleRequest.getSubmittedOnDate(), rejectedOnDate)) { dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rejectedOnDateParam).failWithCode("before.submission.date", "Rejection date cannot be before the request submission date."); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java index ac794d877..3bb566850 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java @@ -24,6 +24,7 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MoneyHelper; import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData; import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO; @@ -113,10 +114,10 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP } for (LoanTermVariationsData loanTermVariation : loanApplicationTerms.getLoanTermVariations().getDueDateVariation()) { - if (rescheduleFromDate.isBefore(loanTermVariation.getTermVariationApplicableFrom())) { + if (DateUtils.isBefore(rescheduleFromDate, loanTermVariation.getTermVariationApplicableFrom())) { LocalDate applicableDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(rescheduleFromDate, loanApplicationTerms, false); - if (loanTermVariation.getTermVariationApplicableFrom().equals(applicableDate)) { + if (DateUtils.isEqual(loanTermVariation.getTermVariationApplicableFrom(), applicableDate)) { LocalDate adjustedDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(adjustedApplicableDate, loanApplicationTerms, false); loanTermVariation.setApplicableFromDate(adjustedDate); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java index 27d798cf9..5ee8dd060 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java @@ -272,12 +272,12 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue(); List installments = loan.getRepaymentScheduleInstallments(); for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getDueDate().isEqual(rescheduleFromLocDate) || installment.getDueDate().isEqual(endDateLocDate) - || (installment.getDueDate().isAfter(rescheduleFromLocDate) && installment.getDueDate().isBefore(endDateLocDate))) { + if (!DateUtils.isBefore(installment.getDueDate(), rescheduleFromLocDate) + && !DateUtils.isAfter(installment.getDueDate(), endDateLocDate)) { createLoanTermVariations(loanRescheduleRequest, termType, loan, installment.getDueDate(), installment.getDueDate(), loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent); } - if (installment.getDueDate().isAfter(endDateLocDate)) { + if (DateUtils.isAfter(installment.getDueDate(), endDateLocDate)) { break; } } @@ -394,8 +394,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche activeLoanTermVariation.markAsInactive(); rescheduleFromDate = activeLoanTermVariation.fetchTermApplicaDate(); dueDateVariationInCurrentRequest.setTermApplicableFrom(rescheduleFromDate); - } else if (!activeLoanTermVariation.fetchTermApplicaDate().isBefore(fromScheduleDate)) { - while (currentScheduleDate.isBefore(activeLoanTermVariation.fetchTermApplicaDate())) { + } else if (!DateUtils.isBefore(activeLoanTermVariation.fetchTermApplicaDate(), fromScheduleDate)) { + while (DateUtils.isBefore(currentScheduleDate, activeLoanTermVariation.fetchTermApplicaDate())) { currentScheduleDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(currentScheduleDate, loanApplicationTerms, false); modifiedScheduleDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(modifiedScheduleDate, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java index 0b9f35062..8252e309d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java @@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanproduct.LoanProductConstants; import org.springframework.beans.factory.annotation.Autowired; @@ -166,8 +167,7 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper { private void validateRepaymentsStartingFromDateIsAfterDisbursementDate(final List dataValidationErrors, final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate) { - if (expectedDisbursementDate != null && repaymentsStartingFromDate != null - && expectedDisbursementDate.isAfter(repaymentsStartingFromDate)) { + if (repaymentsStartingFromDate != null && DateUtils.isAfter(expectedDisbursementDate, repaymentsStartingFromDate)) { final ApiParameterError error = ApiParameterError.parameterError( "validation.msg.loan.expectedDisbursementDate.cannot.be.after.first.repayment.date", "The parameter expectedDisbursementDate has a date which falls after the date for repaymentsStartingFromDate.", diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java index e0d48ea3b..82c73c9ae 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java @@ -41,6 +41,7 @@ import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.accountdetails.domain.AccountType; import org.apache.fineract.portfolio.calendar.service.CalendarUtils; import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; @@ -1182,7 +1183,7 @@ public final class LoanApplicationCommandFromApiJsonHelper { if (jsonObject2.has(LoanApiConstants.expectedDisbursementDateParameterName)) { LocalDate date2 = this.fromApiJsonHelper.extractLocalDateNamed( LoanApiConstants.expectedDisbursementDateParameterName, jsonObject2, dateFormat, locale); - if (date1.isAfter(date2)) { + if (DateUtils.isAfter(date1, date2)) { baseDataValidator.reset().parameter(LoanApiConstants.disbursementDataParameterName) .failWithCode(LoanApiConstants.DISBURSEMENT_DATES_NOT_IN_ORDER); } @@ -1196,7 +1197,6 @@ public final class LoanApplicationCommandFromApiJsonHelper { public void validateLoanMultiDisbursementDate(final JsonElement element, final DataValidatorBuilder baseDataValidator, LocalDate expectedDisbursement, BigDecimal totalPrincipal) { - this.validateDisbursementsAreDatewiseOrdered(element, baseDataValidator); final JsonObject topLevelJsonElement = element.getAsJsonObject(); @@ -1228,7 +1228,8 @@ public final class LoanApplicationCommandFromApiJsonHelper { if (i == 0 && expectedDisbursementDate != null && !expectedDisbursement.equals(expectedDisbursementDate)) { baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName) .failWithCode(LoanApiConstants.DISBURSEMENT_DATE_START_WITH_ERROR); - } else if (i > 0 && expectedDisbursementDate != null && expectedDisbursementDate.isBefore(expectedDisbursement)) { + } else if (i > 0 && expectedDisbursementDate != null + && DateUtils.isBefore(expectedDisbursementDate, expectedDisbursement)) { baseDataValidator.reset().parameter(LoanApiConstants.disbursementDataParameterName) .failWithCode(LoanApiConstants.DISBURSEMENT_DATE_BEFORE_ERROR); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java index dfe907b70..27b4d167c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java @@ -35,6 +35,7 @@ import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlat import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ExternalIdFactory; +import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; @@ -114,12 +115,12 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat loanWaiverTransactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId()); } - if (accrualData.getDueDateAsLocaldate().isAfter(tillDate)) { + if (DateUtils.isAfter(accrualData.getDueDateAsLocaldate(), tillDate)) { if (accruedTill == null || firstTime) { accruedTill = accrualData.getAccruedTill(); firstTime = false; } - if (accruedTill == null || accruedTill.isBefore(tillDate)) { + if (accruedTill == null || DateUtils.isBefore(accruedTill, tillDate)) { updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), tillDate); updateInterestIncome(accrualData, loanWaiverTransactionData, loanWaiverScheduleData, tillDate); addAccrualTillSpecificDate(tillDate, accrualData); @@ -135,9 +136,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat private void addAccrualTillSpecificDate(final LocalDate tillDate, final LoanScheduleAccrualData accrualData) { LocalDate interestStartDate = accrualData.getFromDateAsLocaldate(); - if (accrualData.getInterestCalculatedFrom() != null - && accrualData.getFromDateAsLocaldate().isBefore(accrualData.getInterestCalculatedFrom())) { - if (accrualData.getInterestCalculatedFrom().isBefore(accrualData.getDueDateAsLocaldate())) { + if (DateUtils.isBefore(accrualData.getFromDateAsLocaldate(), accrualData.getInterestCalculatedFrom())) { + if (DateUtils.isBefore(accrualData.getInterestCalculatedFrom(), accrualData.getDueDateAsLocaldate())) { interestStartDate = accrualData.getInterestCalculatedFrom(); } else { interestStartDate = accrualData.getDueDateAsLocaldate(); @@ -146,8 +146,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat int totalNumberOfDays = Math.toIntExact(ChronoUnit.DAYS.between(interestStartDate, accrualData.getDueDateAsLocaldate())); LocalDate startDate = accrualData.getFromDateAsLocaldate(); - if (accrualData.getInterestCalculatedFrom() != null && startDate.isBefore(accrualData.getInterestCalculatedFrom())) { - if (accrualData.getInterestCalculatedFrom().isBefore(tillDate)) { + if (DateUtils.isBefore(startDate, accrualData.getInterestCalculatedFrom())) { + if (DateUtils.isBefore(accrualData.getInterestCalculatedFrom(), tillDate)) { startDate = accrualData.getInterestCalculatedFrom(); } else { startDate = tillDate; @@ -291,7 +291,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat scheduleAccrualData.getRepaymentScheduleId()); String updateLoan = "UPDATE m_loan SET accrued_till=?, last_modified_by=?, last_modified_on_utc=? WHERE id=?"; - this.jdbcTemplate.update(updateLoan, accruedTill, user.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), + this.jdbcTemplate.update(updateLoan, accruedTill, user.getId(), DateUtils.getAuditOffsetDateTime(), scheduleAccrualData.getLoanId()); businessEventNotifierService.notifyPostBusinessEvent(new LoanAccrualTransactionCreatedBusinessEvent(loanTransaction)); @@ -380,9 +380,10 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat LocalDate scheduleEndDate = accrualData.getDueDateAsLocaldate(); for (LoanChargeData loanCharge : chargesData) { BigDecimal chargeAmount = BigDecimal.ZERO; - if (((accrualData.getInstallmentNumber() == 1 && loanCharge.getSubmittedOnDate().isEqual(startDate) - && loanCharge.getDueDate().isEqual(startDate)) || loanCharge.getDueDate().isAfter(startDate)) - && !loanCharge.getSubmittedOnDate().isAfter(endDate) && !loanCharge.getDueDate().isAfter(scheduleEndDate)) { + if (((accrualData.getInstallmentNumber() == 1 && DateUtils.isEqual(startDate, loanCharge.getSubmittedOnDate()) + && DateUtils.isEqual(startDate, loanCharge.getDueDate())) || DateUtils.isBefore(startDate, loanCharge.getDueDate())) + && !DateUtils.isBefore(endDate, loanCharge.getSubmittedOnDate()) + && !DateUtils.isBefore(scheduleEndDate, loanCharge.getDueDate())) { chargeAmount = loanCharge.getAmount(); if (loanCharge.getAmountUnrecognized() != null) { chargeAmount = chargeAmount.subtract(loanCharge.getAmountUnrecognized()); @@ -424,7 +425,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat for (LoanChargeData loanCharge : chargesData) { BigDecimal chargeAmount = BigDecimal.ZERO; if (loanCharge.getDueDate() == null) { - if (loanCharge.isInstallmentFee() && accrualData.getDueDateAsLocaldate().isEqual(endDate)) { + if (loanCharge.isInstallmentFee() && DateUtils.isEqual(endDate, accrualData.getDueDateAsLocaldate())) { Collection installmentData = loanCharge.getInstallmentChargeData(); for (LoanInstallmentChargeData installmentChargeData : installmentData) { @@ -452,8 +453,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat } } } - } else if (((accrualData.getInstallmentNumber() == 1 && loanCharge.getDueDate().isEqual(startDate)) - || loanCharge.getDueDate().isAfter(startDate)) && !loanCharge.getDueDate().isAfter(endDate)) { + } else if (((accrualData.getInstallmentNumber() == 1 && DateUtils.isEqual(loanCharge.getDueDate(), startDate)) + || DateUtils.isAfter(loanCharge.getDueDate(), startDate)) && !DateUtils.isAfter(loanCharge.getDueDate(), endDate)) { chargeAmount = loanCharge.getAmount(); if (loanCharge.getAmountUnrecognized() != null) { chargeAmount = chargeAmount.subtract(loanCharge.getAmountUnrecognized()); @@ -501,22 +502,23 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat Collection loanTransactionDatas = new ArrayList<>(); for (LoanTransactionData loanTransactionData : loanWaiverTransactions) { - if (!loanTransactionData.getDate().isAfter(accrualData.getFromDateAsLocaldate()) - || (loanTransactionData.getDate().isAfter(accrualData.getFromDateAsLocaldate()) - && !loanTransactionData.getDate().isAfter(accrualData.getDueDateAsLocaldate()) - && !loanTransactionData.getDate().isAfter(tillDate))) { + LocalDate transactionDate = loanTransactionData.getDate(); + if (!DateUtils.isAfter(transactionDate, accrualData.getFromDateAsLocaldate()) + || (DateUtils.isAfter(transactionDate, accrualData.getFromDateAsLocaldate()) + && !DateUtils.isAfter(transactionDate, accrualData.getDueDateAsLocaldate()) + && !DateUtils.isAfter(transactionDate, tillDate))) { loanTransactionDatas.add(loanTransactionData); } } Iterator iterator = loanTransactionDatas.iterator(); for (LoanSchedulePeriodData loanSchedulePeriodData : loanSchedulePeriodDataList) { - if (recognized.compareTo(BigDecimal.ZERO) <= 0 && unrecognized.compareTo(BigDecimal.ZERO) <= 0 && iterator.hasNext()) { + if (MathUtil.isLessThanOrEqualZero(recognized) && MathUtil.isLessThanOrEqualZero(unrecognized) && iterator.hasNext()) { LoanTransactionData loanTransactionData = iterator.next(); recognized = recognized.add(loanTransactionData.getInterestPortion()); unrecognized = unrecognized.add(loanTransactionData.getUnrecognizedIncomePortion()); } - if (loanSchedulePeriodData.getDueDate().isBefore(accrualData.getDueDateAsLocaldate())) { + if (DateUtils.isBefore(loanSchedulePeriodData.getDueDate(), accrualData.getDueDateAsLocaldate())) { remainingAmt = remainingAmt.add(loanSchedulePeriodData.getInterestWaived()); if (recognized.compareTo(remainingAmt) > 0) { recognized = recognized.subtract(remainingAmt); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index ea34b502a..925031c7a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -53,6 +53,7 @@ import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRu import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.infrastructure.dataqueries.data.EntityTables; import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum; @@ -287,7 +288,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa "Topup on loan with multi-tranche disbursal and without interest recalculation is not supported."); } final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate(); - if (!newLoanApplication.getSubmittedOnDate().isAfter(disbursalDateOfLoanToClose)) { + if (!DateUtils.isAfter(newLoanApplication.getSubmittedOnDate(), disbursalDateOfLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date", "Submitted date of this loan application " + newLoanApplication.getSubmittedOnDate() @@ -298,7 +299,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa "loanIdToClose is invalid, Currency code is different."); } final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate(); - if (newLoanApplication.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) { + if (DateUtils.isBefore(newLoanApplication.getDisbursementDate(), lastUserTransactionOnLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed", "Disbursal date of this loan application " + newLoanApplication.getDisbursementDate() @@ -867,7 +868,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa "Topup on loan with multi-tranche disbursal and without interest recalculation is not supported."); } final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate(); - if (!existingLoanApplication.getSubmittedOnDate().isAfter(disbursalDateOfLoanToClose)) { + if (!DateUtils.isAfter(existingLoanApplication.getSubmittedOnDate(), disbursalDateOfLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date", "Submitted date of this loan application " + existingLoanApplication.getSubmittedOnDate() @@ -878,7 +879,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa "loanIdToClose is invalid, Currency code is different."); } final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate(); - if (existingLoanApplication.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) { + if (DateUtils.isBefore(existingLoanApplication.getDisbursementDate(), lastUserTransactionOnLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed", "Disbursal date of this loan application " + existingLoanApplication.getDisbursementDate() @@ -1380,7 +1381,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate(); - if (loan.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) { + if (DateUtils.isBefore(loan.getDisbursementDate(), lastUserTransactionOnLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed", "Disbursal date of this loan application " + loan.getDisbursementDate() @@ -1634,19 +1635,19 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final LocalDate submittedOnDate = loan.getSubmittedOnDate(); String defaultUserMessage = ""; - if (startDate != null && submittedOnDate.isBefore(startDate)) { + if (DateUtils.isBefore(submittedOnDate, startDate)) { defaultUserMessage = "submittedOnDate cannot be before the loan product startDate."; throw new LoanApplicationDateException("submitted.on.date.cannot.be.before.the.loan.product.start.date", defaultUserMessage, submittedOnDate.toString(), startDate.toString()); } - if (closeDate != null && submittedOnDate.isAfter(closeDate)) { + if (closeDate != null && DateUtils.isAfter(submittedOnDate, closeDate)) { defaultUserMessage = "submittedOnDate cannot be after the loan product closeDate."; throw new LoanApplicationDateException("submitted.on.date.cannot.be.after.the.loan.product.close.date", defaultUserMessage, submittedOnDate.toString(), closeDate.toString()); } - if (expectedFirstRepaymentOnDate != null && submittedOnDate.isAfter(expectedFirstRepaymentOnDate)) { + if (expectedFirstRepaymentOnDate != null && DateUtils.isAfter(submittedOnDate, expectedFirstRepaymentOnDate)) { defaultUserMessage = "submittedOnDate cannot be after the loans expectedFirstRepaymentOnDate."; throw new LoanApplicationDateException("submitted.on.date.cannot.be.after.the.loan.expected.first.repayment.date", defaultUserMessage, submittedOnDate.toString(), expectedFirstRepaymentOnDate.toString()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java index 93ecfb0da..f0a245267 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java @@ -32,6 +32,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.core.domain.JdbcSupport; import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.event.business.BusinessEventListener; import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent; @@ -145,12 +146,12 @@ public class LoanArrearsAgingServiceImpl implements LoanArrearsAgingService { LocalDate businessDate = DateUtils.getBusinessLocalDate(); LocalDate overDueSince = businessDate; for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getDueDate().isBefore(businessDate)) { + if (DateUtils.isBefore(installment.getDueDate(), businessDate)) { principalOverdue = principalOverdue.add(installment.getPrincipalOutstanding(loan.getCurrency()).getAmount()); interestOverdue = interestOverdue.add(installment.getInterestOutstanding(loan.getCurrency()).getAmount()); feeOverdue = feeOverdue.add(installment.getFeeChargesOutstanding(loan.getCurrency()).getAmount()); penaltyOverdue = penaltyOverdue.add(installment.getPenaltyChargesOutstanding(loan.getCurrency()).getAmount()); - if (installment.isNotFullyPaidOff() && overDueSince.isAfter(installment.getDueDate())) { + if (installment.isNotFullyPaidOff() && DateUtils.isAfter(overDueSince, installment.getDueDate())) { overDueSince = installment.getDueDate(); } } @@ -208,8 +209,8 @@ public class LoanArrearsAgingServiceImpl implements LoanArrearsAgingService { .add(loanSchedulePeriodData.getFeeChargesDue().subtract(loanSchedulePeriodData.getFeeChargesPaid())); penaltyOverdue = penaltyOverdue .add(loanSchedulePeriodData.getPenaltyChargesDue().subtract(loanSchedulePeriodData.getPenaltyChargesPaid())); - if (overDueSince.isAfter(loanSchedulePeriodData.getDueDate()) && loanSchedulePeriodData.getPrincipalDue() - .subtract(loanSchedulePeriodData.getPrincipalPaid()).compareTo(BigDecimal.ZERO) > 0) { + if (DateUtils.isAfter(overDueSince, loanSchedulePeriodData.getDueDate()) && MathUtil + .isGreaterThan(loanSchedulePeriodData.getPrincipalDue(), loanSchedulePeriodData.getPrincipalPaid())) { overDueSince = loanSchedulePeriodData.getDueDate(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueService.java index 23bdf788f..6c7abcca3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueService.java @@ -65,8 +65,7 @@ public class LoanCalculateRepaymentPastDueService { List loanRepayments = loan.getRepaymentScheduleInstallments(); LocalDate currentBusinessDate = DateUtils.getBusinessLocalDate(); return loanRepayments.stream() - .filter((repayment) -> (!repayment.isObligationsMet() - && (repayment.getDueDate().isBefore(currentBusinessDate) || repayment.getDueDate().isEqual(currentBusinessDate)))) + .filter(repayment -> (!repayment.isObligationsMet() && !DateUtils.isAfter(repayment.getDueDate(), currentBusinessDate))) .collect(Collectors.toList()); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java index 5dd39775f..ebfbd5cd2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java @@ -33,6 +33,7 @@ import lombok.RequiredArgsConstructor; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.portfolio.charge.domain.Charge; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; @@ -301,7 +302,7 @@ public class LoanChargeAssembler { if (chargeDefinition.getChargeTimeType().equals(ChargeTimeType.SPECIFIED_DUE_DATE.getValue()) && loan.isMultiDisburmentLoan()) { amountPercentageAppliedTo = BigDecimal.ZERO; for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) { - if (!loanDisbursementDetails.expectedDisbursementDate().isAfter(dueDate)) { + if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), dueDate)) { amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal()); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java index d155d1911..7bebdf28a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java @@ -164,13 +164,12 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService; private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) { - return e.getFromDate().isBefore(loanCharge.getDueDate()) && !loanCharge.getDueDate().isAfter(e.getDueDate()); + return DateUtils.isAfter(loanCharge.getDueDate(), e.getFromDate()) && !DateUtils.isAfter(loanCharge.getDueDate(), e.getDueDate()); } @Transactional @Override public CommandProcessingResult addLoanCharge(final Long loanId, final JsonCommand command) { - this.loanChargeApiJsonValidator.validateAddLoanCharge(command.json()); Loan loan = this.loanAssembler.assembleFrom(loanId); @@ -213,7 +212,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo validateAddLoanCharge(loan, chargeDefinition, loanCharge); addCharge(loan, chargeDefinition, loanCharge); isAppliedOnBackDate = true; - if (recalculateFrom.isAfter(disbursementDetail.expectedDisbursementDateAsLocalDate())) { + if (DateUtils.isAfter(recalculateFrom, disbursementDetail.expectedDisbursementDateAsLocalDate())) { recalculateFrom = disbursementDetail.expectedDisbursementDateAsLocalDate(); } needToGenerateNewExternalId = true; @@ -231,7 +230,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo validateAddLoanCharge(loan, chargeDefinition, loanCharge); isAppliedOnBackDate = addCharge(loan, chargeDefinition, loanCharge); - if (loanCharge.getDueLocalDate() == null || recalculateFrom.isAfter(loanCharge.getDueLocalDate())) { + if (loanCharge.getDueLocalDate() == null || DateUtils.isAfter(recalculateFrom, loanCharge.getDueLocalDate())) { isAppliedOnBackDate = true; recalculateFrom = loanCharge.getDueLocalDate(); } @@ -366,8 +365,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo throw new LoanChargeWaiveCannotBeReversedException( LoanChargeWaiveCannotBeReversedException.LoanChargeWaiveCannotUndoReason.LOAN_INACTIVE, loanCharge.getId()); } - if (loan.isChargedOff() && (loanTransaction.getTransactionDate().isBefore(loan.getChargedOffOnDate()) - || loanTransaction.getTransactionDate().isEqual(loan.getChargedOffOnDate()))) { + if (loan.isChargedOff() && !DateUtils.isAfter(loanTransaction.getTransactionDate(), loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Undo Loan transaction: " + loanTransaction.getId() + " is not allowed before or on the date when the loan got charged-off", @@ -743,17 +741,17 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo overdueInstallment.getPeriodNumber(), command); loan = overdueDTO.getLoan(); runInterestRecalculation = runInterestRecalculation || overdueDTO.isRunInterestRecalculation(); - if (recalculateFrom.isAfter(overdueDTO.getRecalculateFrom())) { + if (DateUtils.isAfter(recalculateFrom, overdueDTO.getRecalculateFrom())) { recalculateFrom = overdueDTO.getRecalculateFrom(); } - if (lastChargeDate == null || overdueDTO.getLastChargeAppliedDate().isAfter(lastChargeDate)) { + if (lastChargeDate == null || DateUtils.isAfter(overdueDTO.getLastChargeAppliedDate(), lastChargeDate)) { lastChargeDate = overdueDTO.getLastChargeAppliedDate(); } } if (loan != null) { boolean reprocessRequired = true; LocalDate recalculatedTill = loan.fetchInterestRecalculateFromDate(); - if (recalculateFrom.isAfter(recalculatedTill)) { + if (DateUtils.isAfter(recalculateFrom, recalculatedTill)) { recalculateFrom = recalculatedTill; } @@ -946,12 +944,11 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null, chargeDefinition.getName()); } else if (loanCharge.getDueLocalDate() != null - && loanCharge.getDueLocalDate().isBefore(loan.getLastUserTransactionForChargeCalc())) { + && DateUtils.isBefore(loanCharge.getDueLocalDate(), loan.getLastUserTransactionForChargeCalc())) { final String defaultUserMessage = "charge with date before last transaction date can not be added to loan."; throw new LoanChargeCannotBeAddedException("loanCharge", "date.is.before.last.transaction.date", defaultUserMessage, null, chargeDefinition.getName()); } else if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - if (loanCharge.isInstalmentFee() && loan.getStatus().isActive()) { final String defaultUserMessage = "installment charge addition not allowed after disbursement"; throw new LoanChargeCannotBeAddedException("loanCharge", "installment.charge", defaultUserMessage, null, @@ -986,7 +983,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo if (!loan.isInterestBearing() && loanCharge.isSpecifiedDueDate()) { LoanRepaymentScheduleInstallment latestRepaymentScheduleInstalment = loan.getRepaymentScheduleInstallments() .get(loan.getLoanRepaymentScheduleInstallmentsSize() - 1); - if (loanCharge.getDueDate().isAfter(latestRepaymentScheduleInstalment.getDueDate())) { + if (DateUtils.isAfter(loanCharge.getDueDate(), latestRepaymentScheduleInstalment.getDueDate())) { if (latestRepaymentScheduleInstalment.isAdditional()) { latestRepaymentScheduleInstalment.updateDueDate(loanCharge.getDueDate()); } else { @@ -1003,15 +1000,13 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo loanCharge = this.loanChargeRepository.saveAndFlush(loanCharge); - /** - * we want to apply charge transactions only for those loans charges that are applied when a loan is active and - * the loan product uses Upfront Accruals - **/ + // we want to apply charge transactions only for those loans charges that are applied when a loan is active and + // the loan product uses Upfront Accruals if (loan.getStatus().isActive() && loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) { final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null); this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction); } - return loanCharge.getDueLocalDate() == null || DateUtils.getBusinessLocalDate().isAfter(loanCharge.getDueLocalDate()); + return DateUtils.isBeforeBusinessDate(loanCharge.getDueLocalDate()); } private LoanOverdueDTO applyChargeToOverdueLoanInstallment(final Loan loan, final Long loanChargeId, final Integer periodNumber, @@ -1037,7 +1032,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo if (feeFrequency == null) { scheduleDates.put(frequencyNumber++, startDate.minusDays(diff)); } else { - while (!startDate.isAfter(DateUtils.getBusinessLocalDate())) { + while (!DateUtils.isDateInTheFuture(startDate)) { scheduleDates.put(frequencyNumber++, startDate.minusDays(diff)); startDate = scheduledDateGenerator.getRepaymentPeriodDate(PeriodFrequencyType.fromInt(feeFrequency), @@ -1070,10 +1065,10 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo boolean isAppliedOnBackDate = addCharge(loan, chargeDefinition, loanCharge); runInterestRecalculation = runInterestRecalculation || isAppliedOnBackDate; - if (entry.getValue().isBefore(recalculateFrom)) { + if (DateUtils.isBefore(entry.getValue(), recalculateFrom)) { recalculateFrom = entry.getValue(); } - if (entry.getValue().isAfter(lastChargeAppliedDate)) { + if (DateUtils.isAfter(entry.getValue(), lastChargeAppliedDate)) { lastChargeAppliedDate = entry.getValue(); } } @@ -1088,7 +1083,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo if (lastChargeDate != null) { List installments = loan.getRepaymentScheduleInstallments(); LoanRepaymentScheduleInstallment lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size()); - if (lastChargeDate.isAfter(lastInstallment.getDueDate())) { + if (DateUtils.isAfter(lastChargeDate, lastInstallment.getDueDate())) { if (lastInstallment.isRecalculatedInterestComponent()) { installments.remove(lastInstallment); lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index caedd8077..349b5b999 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -1223,8 +1223,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal()); disbursementPeriodIds.add(data.getId()); } else if (data.isDueForDisbursement(fromDate, dueDate) && !disbursementPeriodIds.contains(data.getId())) { - if (!excludePastUndisbursed || data.isDisbursed() - || !data.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) { + if (!excludePastUndisbursed || data.isDisbursed() || !DateUtils.isBeforeBusinessDate(data.disbursementDate())) { principal = principal.add(data.getPrincipal()); LoanSchedulePeriodData periodData; if (data.getChargeAmount() == null) { @@ -2385,12 +2384,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa final Collection intRates = this.floatingRatesReadPlatformService .retrieveInterestRatePeriods(loanData.getLoanProductId()); for (final InterestRatePeriodData rate : intRates) { - if (loanData.getTimeline() != null && rate.getFromDate().compareTo(loanData.getTimeline().getDisbursementDate()) > 0 - && loanData.isFloatingInterestRate()) { + if (loanData.getTimeline() == null) { + continue; + } + boolean isAfterDisbursement = DateUtils.isAfter(rate.getFromDate(), loanData.getTimeline().getDisbursementDate()); + if (isAfterDisbursement && loanData.isFloatingInterestRate()) { updateInterestRatePeriodData(rate, loanData); intRatePeriodData.add(rate); - } else if (loanData.getTimeline() != null - && rate.getFromDate().compareTo(loanData.getTimeline().getDisbursementDate()) <= 0) { + } else if (!isAfterDisbursement) { updateInterestRatePeriodData(rate, loanData); intRatePeriodData.add(rate); break; @@ -2416,7 +2417,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa } rate.setEffectiveInterestRate(effectiveInterestRate); - if (loan.getTimeline() != null && rate.getFromDate().compareTo(loan.getTimeline().getDisbursementDate()) < 0) { + if (loan.getTimeline() != null && DateUtils.isBefore(rate.getFromDate(), loan.getTimeline().getDisbursementDate())) { rate.setFromDate(loan.getTimeline().getDisbursementDate()); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java index 6ea1add5a..a247bc5ad 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java @@ -281,7 +281,7 @@ public class LoanUtilService { isSkipRepaymentOnFirstMonth = isLoanRepaymentsSyncWithMeeting(loan.group(), historyList.get(0).getCalendar()); } calculatedRepaymentsStartingFromDate = CalendarUtils.getNextRepaymentMeetingDate(historyList.get(0).getRecurrence(), - historyList.get(0).getStartDateLocalDate(), actualDisbursementDate, repayEvery, frequency, workingDays, + historyList.get(0).getStartDate(), actualDisbursementDate, repayEvery, frequency, workingDays, isSkipRepaymentOnFirstMonth, numberOfDays); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 24edd03a2..9e72ff81b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -291,7 +291,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); - if (loan.isChargedOff() && actualDisbursementDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(actualDisbursementDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loanId + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -405,7 +405,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf "Loan to be closed with this topup is not active."); } final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate(); - if (loan.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) { + if (DateUtils.isBefore(loan.getDisbursementDate(), lastUserTransactionOnLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed", "Disbursal date of this loan application " + loan.getDisbursementDate() @@ -1131,7 +1131,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf LocalDate recalculateFrom = null; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - recalculateFrom = transactionToAdjust.getTransactionDate().isAfter(transactionDate) ? transactionDate + recalculateFrom = DateUtils.isAfter(transactionToAdjust.getTransactionDate(), transactionDate) ? transactionDate : transactionToAdjust.getTransactionDate(); } @@ -1149,11 +1149,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.loanTransactionRepository.saveAndFlush(newTransactionDetail); } - /*** + /* * TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the * time being, not a major issue for now as this loop is entered only in edge cases (when a adjustment is made * before the latest payment recorded against the loan) - ***/ + */ if (changedTransactionDetail != null) { for (final Map.Entry mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue()); @@ -1446,7 +1446,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } checkClientOrGroupActive(loan); - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loanId + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -1512,7 +1512,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final Loan loan = this.loanAssembler.assembleFrom(loanId); checkClientOrGroupActive(loan); LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate"); - if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) { + if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) { throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: " + loanId + " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan", @@ -2598,8 +2598,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private void checkIfLoanIsPaidInAdvance(final Long loanId, final BigDecimal transactionAmount) { BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId).getPaidInAdvance(); - if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE - : Boolean.FALSE || transactionAmount.floatValue() > overpaid.floatValue()) { + if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 || transactionAmount.floatValue() > overpaid.floatValue()) { if (overpaid == null) { overpaid = BigDecimal.ZERO; } @@ -2685,7 +2684,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf String noteText = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParamName, element); LoanRescheduleRequest loanRescheduleRequest = null; for (LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) { - if (!loanDisbursementDetails.expectedDisbursementDateAsLocalDate().isAfter(transactionDate) + if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDateAsLocalDate(), transactionDate) && loanDisbursementDetails.actualDisbursementDate() == null) { final String defaultUserMessage = "The loan with undisbursed tranche before foreclosure cannot be foreclosed."; throw new LoanForeclosureException("loan.with.undisbursed.tranche.before.foreclosure.cannot.be.foreclosured", @@ -2732,12 +2731,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf throw new GeneralPlatformDomainRuleException("error.msg.loan.is.already.charged.off", "Loan: " + loanId + " is already charged-off", loanId); } - if (transactionDate.isBefore(loan.getLastUserTransactionDate())) { + if (DateUtils.isBefore(transactionDate, loan.getLastUserTransactionDate())) { throw new GeneralPlatformDomainRuleException("error.msg.loan.charge.off.is.before.than.the.last.user.transaction", "Loan: " + loanId + " charge-off cannot be executed. User transaction was found after the charge-off transaction date!", loanId); } - if (transactionDate.isAfter(DateUtils.getBusinessLocalDate())) { + if (DateUtils.isDateInTheFuture(transactionDate)) { final String errorMessage = "The transaction date cannot be in the future."; throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.cannot.be.a.future.date", errorMessage, transactionDate); @@ -2848,27 +2847,23 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final String errorMessage = "tranches.should.be.disbursed.more.than.one.to.undo.last.disbursal"; throw new LoanMultiDisbursementException(errorMessage); } - } private void syncExpectedDateWithActualDisbursementDate(final Loan loan, LocalDate actualDisbursementDate) { if (!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)) { throw new DateMismatchException(actualDisbursementDate, loan.getExpectedDisbursedOnLocalDate()); } - } private void validateTransactionsForTransfer(final Loan loan, final LocalDate transferDate) { - for (LoanTransaction transaction : loan.getLoanTransactions()) { - if ((transaction.getTransactionDate().isEqual(transferDate) && transaction.getSubmittedOnDate().isEqual(transferDate)) - || transaction.getTransactionDate().isAfter(transferDate)) { + if ((DateUtils.isEqual(transferDate, transaction.getTransactionDate()) + && DateUtils.isEqual(transferDate, transaction.getSubmittedOnDate())) + || DateUtils.isBefore(transferDate, transaction.getTransactionDate())) { throw new GeneralPlatformDomainRuleException(TransferApiConstants.transferClientLoanException, TransferApiConstants.transferClientLoanExceptionMessage, transaction.getCreatedDateTime().toLocalDate(), transferDate); } - } - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java index 91d87a0b3..f4c20667b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -369,7 +369,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo final boolean enableInstallmentLevelDelinquency = rs.getBoolean("enableInstallmentLevelDelinquency"); String status = ""; - if (closeDate != null && closeDate.isBefore(DateUtils.getBusinessLocalDate())) { + if (closeDate != null && DateUtils.isBeforeBusinessDate(closeDate)) { status = "loanProduct.inActive"; } else { status = "loanProduct.active"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java index 978b3eb91..a01510344 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java @@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.entityaccess.domain.FineractEntityAccessType; import org.apache.fineract.infrastructure.entityaccess.service.FineractEntityAccessUtil; import org.apache.fineract.infrastructure.event.business.domain.loan.product.LoanProductCreateBusinessEvent; @@ -369,10 +370,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro final LocalDate startDate = command.localDateValueOfParameterNamed("startDate"); final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate"); - if (startDate != null && closeDate != null) { - if (closeDate.isBefore(startDate)) { - throw new LoanProductDateException(startDate.toString(), closeDate.toString()); - } + if (closeDate != null && DateUtils.isBefore(closeDate, startDate)) { + throw new LoanProductDateException(startDate.toString(), closeDate.toString()); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/domain/Meeting.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/domain/Meeting.java index 0ffe29016..3a758d813 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/domain/Meeting.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/domain/Meeting.java @@ -167,7 +167,7 @@ public class Meeting extends AbstractPersistableCustom { } public boolean isMeetingDateBefore(final LocalDate newStartDate) { - return this.meetingDate != null && newStartDate != null && getMeetingDateLocalDate().isBefore(newStartDate) ? true : false; + return this.meetingDate != null && DateUtils.isBefore(getMeetingDateLocalDate(), newStartDate); } private static boolean isValidMeetingDate(final CalendarInstance calendarInstance, final LocalDate meetingDate, @@ -181,7 +181,7 @@ public class Meeting extends AbstractPersistableCustom { } private boolean isMeetingDateAfter(final LocalDate date) { - return getMeetingDateLocalDate().isAfter(date); + return DateUtils.isAfter(getMeetingDateLocalDate(), date); } public Collection getClientsAttendance() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/search/data/SearchConditions.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/search/data/SearchConditions.java index 7176144fd..633ebe854 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/search/data/SearchConditions.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/search/data/SearchConditions.java @@ -36,18 +36,18 @@ public class SearchConditions { this.searchQuery = searchQueryParam; this.searchResource = searchResource; this.exactMatch = exactMatch; - this.clientSearch = (null == searchResource - || searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTS.name().toLowerCase())) ? true : false; - this.groupSearch = (null == searchResource - || searchResource.toLowerCase().contains(SearchSupportedResources.GROUPS.name().toLowerCase())) ? true : false; - this.loanSeach = (null == searchResource - || searchResource.toLowerCase().contains(SearchSupportedResources.LOANS.name().toLowerCase())) ? true : false; - this.savingSeach = (null == searchResource - || searchResource.toLowerCase().contains(SearchSupportedResources.SAVINGS.name().toLowerCase())) ? true : false; - this.shareSeach = (null == searchResource - || searchResource.toLowerCase().contains(SearchSupportedResources.SHARES.name().toLowerCase())) ? true : false; - this.clientIdentifierSearch = (null == searchResource - || searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTIDENTIFIERS.name().toLowerCase())) ? true : false; + this.clientSearch = null == searchResource + || searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTS.name().toLowerCase()); + this.groupSearch = null == searchResource + || searchResource.toLowerCase().contains(SearchSupportedResources.GROUPS.name().toLowerCase()); + this.loanSeach = null == searchResource + || searchResource.toLowerCase().contains(SearchSupportedResources.LOANS.name().toLowerCase()); + this.savingSeach = null == searchResource + || searchResource.toLowerCase().contains(SearchSupportedResources.SAVINGS.name().toLowerCase()); + this.shareSeach = null == searchResource + || searchResource.toLowerCase().contains(SearchSupportedResources.SHARES.name().toLowerCase()); + this.clientIdentifierSearch = null == searchResource + || searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTIDENTIFIERS.name().toLowerCase()); } public SearchConditions(final String searchQueryParam, final String searchResource, final Boolean clientSearch, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForSavingsImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForSavingsImpl.java index c0089b1e8..7cb5503df 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForSavingsImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForSavingsImpl.java @@ -54,10 +54,8 @@ public class AccountEntityServiceForSavingsImpl implements AccountEntityService @Override public void validateSelfUserAccountMapping(Long accountId) { - - if (!this.appuserSavingsMapperReadService.isSavingsMappedToUser(accountId, this.context.getAuthenticatedUserIfPresent().getId())) { + if (!this.appuserSavingsMapperReadService.isSavingsMappedToUser(accountId, this.context.authenticatedUser().getId())) { throw new SavingsAccountNotFoundException(accountId); - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForShareAccountsImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForShareAccountsImpl.java index a1c8ea814..a2e56a043 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForShareAccountsImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/service/AccountEntityServiceForShareAccountsImpl.java @@ -53,9 +53,8 @@ public class AccountEntityServiceForShareAccountsImpl implements AccountEntitySe @Override public void validateSelfUserAccountMapping(Long accountId) { if (!this.appUserShareAccountsMapperReadPlatformService.isShareAccountsMappedToUser(accountId, - this.context.getAuthenticatedUserIfPresent().getId())) { + this.context.authenticatedUser().getId())) { throw new ShareAccountNotFoundException(accountId); - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java index ffb3e2a07..8662e9d6d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java @@ -36,6 +36,7 @@ import java.util.HashSet; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.portfolio.client.domain.Client; @@ -209,7 +210,7 @@ public class ShareAccount extends AbstractPersistableCustom { public boolean setSubmittedDate(final LocalDate submittedDate) { boolean toReturn = false; - if (this.submittedDate.compareTo(submittedDate) == 0 ? Boolean.FALSE : Boolean.TRUE) { + if (!DateUtils.isEqual(submittedDate, this.submittedDate)) { this.submittedDate = submittedDate; toReturn = true; } @@ -218,7 +219,7 @@ public class ShareAccount extends AbstractPersistableCustom { public boolean setApprovedDate(final LocalDate approvedDate) { boolean toReturn = false; - if (this.approvedDate.compareTo(approvedDate) == 0 ? Boolean.FALSE : Boolean.TRUE) { + if (!DateUtils.isEqual(approvedDate, this.approvedDate)) { this.approvedDate = approvedDate; toReturn = true; } @@ -514,11 +515,11 @@ public class ShareAccount extends AbstractPersistableCustom { public ShareAccountTransaction getShareAccountTransaction(final ShareAccountTransaction transaction) { ShareAccountTransaction returnTrans = null; for (ShareAccountTransaction tran : this.shareAccountTransactions) { - if (tran.getPurchasedDate().compareTo(transaction.getPurchasedDate()) == 0 ? Boolean.TRUE - : Boolean.FALSE && tran.getTotalShares().equals(transaction.getTotalShares()) - && tran.getPurchasePrice().compareTo(transaction.getPurchasePrice()) == 0 ? Boolean.TRUE - : Boolean.FALSE && tran.getTransactionStatus().equals(transaction.getTransactionStatus()) - && tran.getTransactionType().equals(transaction.getTransactionType())) { + if (DateUtils.isEqual(tran.getPurchasedDate(), transaction.getPurchasedDate()) + && tran.getTotalShares().equals(transaction.getTotalShares()) + && tran.getPurchasePrice().compareTo(transaction.getPurchasePrice()) == 0 + && tran.getTransactionStatus().equals(transaction.getTransactionStatus()) + && tran.getTransactionType().equals(transaction.getTransactionType())) { returnTrans = tran; break; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java index a7c16bfce..4f457a1dc 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java @@ -469,7 +469,7 @@ public class ShareAccountDataSerializer { } LocalDate approvedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.approveddate_paramname, element); final LocalDate submittalDate = account.getSubmittedDate(); - if (approvedDate != null && approvedDate.isBefore(submittalDate)) { + if (approvedDate != null && DateUtils.isBefore(approvedDate, submittalDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jsonCommand.dateFormat()) .withLocale(jsonCommand.extractLocale()); final String submittalDateAsString = formatter.format(submittalDate); @@ -610,7 +610,7 @@ public class ShareAccountDataSerializer { LocalDate activatedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.activatedate_paramname, element); baseDataValidator.reset().parameter(ShareAccountApiConstants.activatedate_paramname).value(activatedDate).notNull(); final LocalDate approvedDate = account.getApprovedDate(); - if (activatedDate != null && activatedDate.isBefore(approvedDate)) { + if (activatedDate != null && DateUtils.isBefore(activatedDate, approvedDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jsonCommand.dateFormat()) .withLocale(jsonCommand.extractLocale()); final String submittalDateAsString = formatter.format(approvedDate); @@ -710,7 +710,7 @@ public class ShareAccountDataSerializer { for (ShareAccountTransaction transaction : transactions) { if (!transaction.isChargeTransaction()) { LocalDate transactionDate = transaction.getPurchasedDate(); - if (requestedDate.isBefore(transactionDate)) { + if (DateUtils.isBefore(requestedDate, transactionDate)) { isTransactionBeforeExistingTransactions = true; break; } @@ -867,7 +867,7 @@ public class ShareAccountDataSerializer { for (ShareAccountTransaction transaction : transactions) { if (!transaction.isChargeTransaction() && transaction.isActive()) { LocalDate transactionDate = transaction.getPurchasedDate(); - if (requestedDate.isBefore(transactionDate)) { + if (DateUtils.isBefore(requestedDate, transactionDate)) { isTransactionBeforeExistingTransactions = true; break; } @@ -908,8 +908,8 @@ public class ShareAccountDataSerializer { if (lockinPeriod == null && periodType == null) { return; } - Long totalSharesCanBeRedeemed = Long.valueOf(0); - Long totalSharesPurchasedBeforeRedeem = Long.valueOf(0); + Long totalSharesCanBeRedeemed = 0L; + Long totalSharesPurchasedBeforeRedeem = 0L; boolean isPurchaseTransactionExist = false; Set transactions = account.getShareAccountTransactions(); @@ -917,7 +917,7 @@ public class ShareAccountDataSerializer { if (transaction.isActive() && !transaction.isChargeTransaction()) { LocalDate purchaseDate = transaction.getPurchasedDate(); LocalDate lockinDate = deriveLockinPeriodDuration(lockinPeriod, periodType, purchaseDate); - if (!lockinDate.isAfter(redeemDate)) { + if (!DateUtils.isAfter(lockinDate, redeemDate)) { if (transaction.isPurchasTransaction()) { totalSharesCanBeRedeemed += transaction.getTotalShares(); } else if (transaction.isRedeemTransaction()) { @@ -925,7 +925,7 @@ public class ShareAccountDataSerializer { } } - if (!purchaseDate.isAfter(redeemDate)) { + if (!DateUtils.isAfter(purchaseDate, redeemDate)) { isPurchaseTransactionExist = true; if (transaction.isPurchasTransaction()) { totalSharesPurchasedBeforeRedeem += transaction.getTotalShares(); @@ -1022,7 +1022,7 @@ public class ShareAccountDataSerializer { for (ShareAccountTransaction transaction : transactions) { if (!transaction.isChargeTransaction()) { LocalDate transactionDate = transaction.getPurchasedDate(); - if (closedDate.isBefore(transactionDate)) { + if (DateUtils.isBefore(closedDate, transactionDate)) { isTransactionBeforeExistingTransactions = true; break; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java index d763777b6..efca2075b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java @@ -140,8 +140,8 @@ public class ShareAccountReadPlatformServiceImpl implements ShareAccountReadPlat if (marketDataSet != null && !marketDataSet.isEmpty()) { LocalDate currentDate = DateUtils.getBusinessLocalDate(); for (ShareProductMarketPriceData data : marketDataSet) { - LocalDate futureDate = data.getFromDate(); - if (currentDate.isAfter(futureDate)) { + LocalDate fromDate = data.getFromDate(); + if (DateUtils.isBefore(fromDate, currentDate)) { marketValue = data.getShareValue(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java index 54d495e9b..76c757039 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java @@ -128,7 +128,7 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA private Map populateJournalEntries(final ShareAccount account, final Set transactions) { final Map accountingBridgeData = new HashMap<>(); - Boolean cashBasedAccounting = account.getShareProduct().getAccountingType() == 2 ? Boolean.TRUE : Boolean.FALSE; + Boolean cashBasedAccounting = account.getShareProduct().getAccountingType() == 2; accountingBridgeData.put("cashBasedAccountingEnabled", cashBasedAccounting); accountingBridgeData.put("accrualBasedAccountingEnabled", Boolean.FALSE); accountingBridgeData.put("shareAccountId", account.getId()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java index 0d6babfd0..1caa0f9b5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java @@ -237,7 +237,7 @@ public class ShareProduct extends AbstractAuditableCustom { public boolean setUnitPrice(BigDecimal unitPrice) { boolean returnValue = false; - if (this.unitPrice.compareTo(unitPrice) == 0 ? Boolean.FALSE : Boolean.TRUE) { + if (this.unitPrice.compareTo(unitPrice) != 0) { this.unitPrice = unitPrice; returnValue = true; } @@ -353,7 +353,7 @@ public class ShareProduct extends AbstractAuditableCustom { public boolean setshareCapitalValue(BigDecimal shareCapitalValue) { boolean updated = false; - if (this.shareCapital == null || this.shareCapital.compareTo(shareCapitalValue) == 0 ? Boolean.FALSE : Boolean.TRUE) { + if (this.shareCapital == null || this.shareCapital.compareTo(shareCapitalValue) != 0) { this.shareCapital = shareCapitalValue; updated = true; } @@ -395,8 +395,8 @@ public class ShareProduct extends AbstractAuditableCustom { BigDecimal marketValue = this.unitPrice; if (this.marketPrice != null && !this.marketPrice.isEmpty()) { for (ShareProductMarketPrice data : this.marketPrice) { - LocalDate futureDate = data.getStartDate(); - if (currentDate.compareTo(futureDate) == 0 ? Boolean.TRUE : Boolean.FALSE || currentDate.isAfter(futureDate)) { + LocalDate startDate = data.getStartDate(); + if (!DateUtils.isAfter(startDate, currentDate)) { marketValue = data.getPrice(); } } @@ -406,7 +406,7 @@ public class ShareProduct extends AbstractAuditableCustom { public void addSubscribedShares(final Long subscribedShares) { if (this.totalSubscribedShares == null) { - this.totalSubscribedShares = Long.valueOf(0); + this.totalSubscribedShares = 0L; } this.totalSubscribedShares += subscribedShares; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java index ca76bf94a..30625c22d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java @@ -24,6 +24,7 @@ import java.time.temporal.ChronoUnit; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.products.service.ShareProductReadPlatformService; @@ -106,7 +107,7 @@ public class ShareProductDividendAssembler { if (status.isApproved() && !type.isChargePayment()) { LocalDate shareStartDate = purchasedSharesData.getPurchasedDate(); - if (shareStartDate.isBefore(lastDividendPostDate)) { + if (DateUtils.isBefore(shareStartDate, lastDividendPostDate)) { shareStartDate = lastDividendPostDate; } int numberOfPurchseDays = Math.toIntExact(ChronoUnit.DAYS.between(shareStartDate, postingDate)); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java index 0613a8629..cbb103ff5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java @@ -282,7 +282,7 @@ public class TaxValidator { for (TaxGroupMappings mapping : groupMappings) { if (mapping.getId() != null) { TaxGroupMappings existing = taxGroup.findOneBy(mapping); - if (existing.endDate() != null && mapping.endDate() != null && !existing.endDate().isEqual(mapping.endDate())) { + if (existing.endDate() != null && mapping.endDate() != null && !DateUtils.isEqual(existing.endDate(), mapping.endDate())) { baseDataValidator.reset().parameter(TaxApiConstants.endDateParamName) .failWithCode("can.not.modify.end.date.once.updated"); } else { @@ -335,7 +335,7 @@ public class TaxValidator { if (groupMappingsOne.getTaxComponent().equals(groupMappings.getTaxComponent())) { if (groupMappingsOne.endDate() == null && groupMappings.endDate() == null) { baseDataValidator.reset().parameter(COMPONENT).failWithCode(DATES_ARE_OVERLAPPING); - } else if (groupMappingsOne.startDate().isAfter(groupMappings.startDate())) { + } else if (DateUtils.isAfter(groupMappingsOne.startDate(), groupMappings.startDate())) { baseDataValidator.reset().parameter(COMPONENT_START_DATE).value(groupMappingsOne.startDate()) .validateDateAfter(groupMappings.endDate()); } else { diff --git a/fineract-provider/src/test/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTaskletTest.java b/fineract-provider/src/test/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTaskletTest.java index 35d63c066..cacf22032 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTaskletTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/commands/jobs/PurgeProcessedCommandsTaskletTest.java @@ -81,7 +81,7 @@ public class PurgeProcessedCommandsTaskletTest { // then verify(repository, times(1)).deleteOlderEventsWithStatus(Mockito.any(), Mockito.any()); verify(repository).deleteOlderEventsWithStatus(Mockito.any(), dateCriteriaCaptor.capture()); - OffsetDateTime expectedDateForPurgeCriteriaTest = DateUtils.getOffsetDateTimeOfTenant().minusDays(2); + OffsetDateTime expectedDateForPurgeCriteriaTest = DateUtils.getAuditOffsetDateTime().minusDays(2); OffsetDateTime actualDateForPurgeCriteria = dateCriteriaCaptor.getValue(); assertTrue(expectedDateForPurgeCriteriaTest.toEpochSecond() - actualDateForPurgeCriteria.toEpochSecond() <= 1); assertEquals(RepeatStatus.FINISHED, resultStatus); diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java index 6e744ce82..d5c8401a5 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java @@ -26,10 +26,13 @@ import static org.mockito.Mockito.when; import java.math.BigDecimal; import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.fineract.infrastructure.core.domain.ExternalId; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.charge.domain.Charge; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode; @@ -170,6 +173,68 @@ public class LoanTest { assertEquals(loanTransaction2, userTransaction); } + /** + * Tests {@link Loan#getLastUserTransaction()} where there are user transactions + */ + @Test + public void testTransactionComparator() { + final Loan loan = new Loan(); + LocalDate today = LocalDate.of(2023, 10, 12); + OffsetDateTime now = DateUtils.getAuditOffsetDateTime(); + + LoanTransaction lt1 = new LoanTransaction(); + ReflectionTestUtils.setField(lt1, "id", 1L); + ReflectionTestUtils.setField(lt1, "typeOf", LoanTransactionType.DISBURSEMENT.getValue()); + ReflectionTestUtils.setField(lt1, "dateOf", today); + ReflectionTestUtils.setField(lt1, "createdDate", now); + LoanTransaction lt2 = new LoanTransaction(); + ReflectionTestUtils.setField(lt2, "id", 2L); + ReflectionTestUtils.setField(lt2, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt2, "dateOf", today); + ReflectionTestUtils.setField(lt2, "createdDate", now); + LoanTransaction lt3 = new LoanTransaction(); + ReflectionTestUtils.setField(lt3, "id", 3L); + ReflectionTestUtils.setField(lt3, "typeOf", LoanTransactionType.REPAYMENT.getValue()); + ReflectionTestUtils.setField(lt3, "dateOf", today); + ReflectionTestUtils.setField(lt3, "createdDate", now); + ReflectionTestUtils.setField(lt3, "reversed", true); + LoanTransaction lt4 = new LoanTransaction(); + ReflectionTestUtils.setField(lt4, "id", 4L); + ReflectionTestUtils.setField(lt4, "typeOf", LoanTransactionType.WAIVE_INTEREST.getValue()); + ReflectionTestUtils.setField(lt4, "dateOf", today); + ReflectionTestUtils.setField(lt4, "createdDate", now); + LoanTransaction lt5 = new LoanTransaction(); + ReflectionTestUtils.setField(lt5, "id", 5L); + ReflectionTestUtils.setField(lt5, "typeOf", LoanTransactionType.INCOME_POSTING.getValue()); + ReflectionTestUtils.setField(lt5, "dateOf", today); + ReflectionTestUtils.setField(lt5, "createdDate", now); + LoanTransaction lt6 = new LoanTransaction(); + ReflectionTestUtils.setField(lt6, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt6, "dateOf", today.minusDays(2)); + LoanTransaction lt7 = new LoanTransaction(); + ReflectionTestUtils.setField(lt7, "id", 7L); + ReflectionTestUtils.setField(lt7, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt7, "dateOf", today.minusDays(2)); + LoanTransaction lt8 = new LoanTransaction(); + ReflectionTestUtils.setField(lt8, "id", 8L); + ReflectionTestUtils.setField(lt8, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt8, "dateOf", today.minusDays(2)); + ReflectionTestUtils.setField(lt8, "createdDate", now.minusMinutes(2)); + + List transactions = Arrays.asList(lt1, lt2, lt3, lt4, lt5, lt6, lt7, lt8); + transactions.sort(LoanTransactionComparator.INSTANCE); + + assertEquals(8L, transactions.get(0).getId()); + assertEquals(7L, transactions.get(1).getId()); + assertNull(transactions.get(2).getId()); + assertEquals(today.minusDays(2), transactions.get(2).getTransactionDate()); + assertEquals(5L, transactions.get(3).getId()); + assertEquals(4L, transactions.get(4).getId()); + assertEquals(1L, transactions.get(5).getId()); + assertEquals(2L, transactions.get(6).getId()); + assertEquals(3L, transactions.get(7).getId()); + } + /** * Builds a new loan charge. * diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java index db4dfe687..c8c09f947 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java @@ -119,7 +119,7 @@ public class AccountingScenarioIntegrationTest { private SchedulerJobHelper schedulerJobHelper; private PeriodicAccrualAccountingHelper periodicAccrualAccountingHelper; - private TimeZone systemTimeZone; + private TimeZone tenantTimeZone; @BeforeEach public void setup() { @@ -135,7 +135,7 @@ public class AccountingScenarioIntegrationTest { this.schedulerJobHelper = new SchedulerJobHelper(requestSpec); this.periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(requestSpec, responseSpec); - this.systemTimeZone = TimeZone.getTimeZone(Utils.TENANT_TIME_ZONE); + this.tenantTimeZone = TimeZone.getTimeZone(Utils.TENANT_TIME_ZONE); } @Test @@ -805,8 +805,8 @@ public class AccountingScenarioIntegrationTest { final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US); - final LocalDate localDate = LocalDate.now(this.systemTimeZone.toZoneId()); - final ZonedDateTime currentDate = ZonedDateTime.of(localDate, LocalTime.MIDNIGHT, this.systemTimeZone.toZoneId()); + final LocalDate localDate = LocalDate.now(this.tenantTimeZone.toZoneId()); + final ZonedDateTime currentDate = ZonedDateTime.of(localDate, LocalTime.MIDNIGHT, this.tenantTimeZone.toZoneId()); ZonedDateTime zonedDate = currentDate.minusDays(4); final String LOAN_DISBURSEMENT_DATE = dateFormat.format(zonedDate); @@ -907,7 +907,7 @@ public class AccountingScenarioIntegrationTest { DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); - Calendar todayDate = Calendar.getInstance(this.systemTimeZone); + Calendar todayDate = Calendar.getInstance(this.tenantTimeZone); todayDate.add(Calendar.DATE, -4); @@ -915,7 +915,7 @@ public class AccountingScenarioIntegrationTest { todayDate.add(Calendar.MONTH, 2); - todayDate = Calendar.getInstance(this.systemTimeZone); + todayDate = Calendar.getInstance(this.tenantTimeZone); todayDate.add(Calendar.DATE, -2); String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java index 66b0c41f6..d9833a12c 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java @@ -87,6 +87,7 @@ import org.apache.fineract.client.models.PostLoansResponse; import org.apache.fineract.client.models.PutChargeTransactionChangesRequest; import org.apache.fineract.client.util.CallFailedRuntimeException; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CollateralManagementHelper; @@ -6308,7 +6309,7 @@ public class ClientLoanIntegrationTest { LocalDate expectedMaturityDate = loanDetails.getTimeline().getExpectedMaturityDate(); LocalDate actualMaturityDate = loanDetails.getTimeline().getActualMaturityDate(); - assertTrue(expectedMaturityDate.isEqual(actualMaturityDate)); + assertTrue(DateUtils.isEqual(expectedMaturityDate, actualMaturityDate)); LOAN_TRANSACTION_HELPER.makeRepayment("04 September 2022", Float.parseFloat("500"), loanID); LOAN_TRANSACTION_HELPER.makeRepayment("05 September 2022", Float.parseFloat("700"), loanID); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java index e7cd2062e..4e560a925 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java @@ -40,6 +40,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; @@ -670,7 +671,7 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe LocalDate downPaymentEntryDate = LocalDate.of(downPaymentDateAsArray.get(0), downPaymentDateAsArray.get(1), downPaymentDateAsArray.get(2)); - if (transactionDate.isEqual(downPaymentEntryDate)) { + if (DateUtils.isEqual(transactionDate, downPaymentEntryDate)) { isTransactionFound = true; assertEquals(principalPortion, Float.valueOf(String.valueOf(transactions.get(i).get("principalPortion"))), "Mismatch in transaction amounts"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionOnChargeSubmittedDateTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionOnChargeSubmittedDateTest.java index b804c5730..4ba40865e 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionOnChargeSubmittedDateTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionOnChargeSubmittedDateTest.java @@ -41,6 +41,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; @@ -746,7 +747,7 @@ public class LoanAccrualTransactionOnChargeSubmittedDateTest { LocalDate accrualEntryDate = LocalDate.of(accrualEntryDateAsArray.get(0), accrualEntryDateAsArray.get(1), accrualEntryDateAsArray.get(2)); - if (transactionDate.isEqual(accrualEntryDate)) { + if (DateUtils.isEqual(transactionDate, accrualEntryDate)) { isTransactionFound = true; verifyAmounts(0.0f, 0.0f, 10.0f, Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))), Float.valueOf(String.valueOf(transactions.get(i).get("feeChargesPortion"))), @@ -875,7 +876,7 @@ public class LoanAccrualTransactionOnChargeSubmittedDateTest { LocalDate accrualEntryDate = LocalDate.of(accrualEntryDateAsArray.get(0), accrualEntryDateAsArray.get(1), accrualEntryDateAsArray.get(2)); - if (transactionDate.isEqual(accrualEntryDate)) { + if (DateUtils.isEqual(transactionDate, accrualEntryDate)) { isTransactionFound = true; assertEquals(interestPortion, Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))), "Mismatch in transaction amounts"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java index e0fabe178..f2d985d2c 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java @@ -38,6 +38,7 @@ import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; @@ -267,7 +268,7 @@ public class LoanAccrualTransactionReversalTest { LocalDate accrualEntryDate = LocalDate.of(accrualEntryDateAsArray.get(0), accrualEntryDateAsArray.get(1), accrualEntryDateAsArray.get(2)); - if (transactionDate.isEqual(accrualEntryDate)) { + if (DateUtils.isEqual(transactionDate, accrualEntryDate)) { isTransactionFound = true; assertEquals(interestPortion, Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))), "Mismatch in transaction amounts"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanMultipleDisbursementRepaymentScheduleTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanMultipleDisbursementRepaymentScheduleTest.java index 7ebf448ec..cef95ea9d 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanMultipleDisbursementRepaymentScheduleTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanMultipleDisbursementRepaymentScheduleTest.java @@ -40,6 +40,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; @@ -188,7 +189,7 @@ public class LoanMultipleDisbursementRepaymentScheduleTest { LocalDate accrualEntryDate = LocalDate.of(accrualEntryDateAsArray.get(0), accrualEntryDateAsArray.get(1), accrualEntryDateAsArray.get(2)); - if (transactionDate.isEqual(accrualEntryDate)) { + if (DateUtils.isEqual(transactionDate, accrualEntryDate)) { isTransactionFound = true; assertEquals(interestPortion, Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))), "Mismatch in transaction amounts"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java index 70739307c..f9dccc356 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java @@ -41,6 +41,7 @@ import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.client.models.PutLoanProductsProductIdRequest; import org.apache.fineract.client.models.PutLoanProductsProductIdResponse; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CommonConstants; @@ -605,7 +606,7 @@ public class LoanProductWithDownPaymentConfigurationTest { LocalDate downPaymentEntryDate = LocalDate.of(downPaymentDateAsArray.get(0), downPaymentDateAsArray.get(1), downPaymentDateAsArray.get(2)); - if (transactionDate.isEqual(downPaymentEntryDate)) { + if (DateUtils.isEqual(transactionDate, downPaymentEntryDate)) { isTransactionFound = true; assertEquals(principalPortion, Float.valueOf(String.valueOf(transactions.get(i).get("principalPortion"))), "Mismatch in transaction amounts"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/OfficeIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/OfficeIntegrationTest.java index 39588993e..9040422b5 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/OfficeIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/OfficeIntegrationTest.java @@ -28,6 +28,7 @@ import java.time.LocalDate; import java.util.UUID; import org.apache.fineract.client.models.GetOfficesResponse; import org.apache.fineract.client.models.PutOfficesOfficeIdResponse; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.OfficeDomain; import org.apache.fineract.integrationtests.common.OfficeHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -97,6 +98,6 @@ public class OfficeIntegrationTest { GetOfficesResponse newOffice = officeResult.body(); Assertions.assertTrue(name.equals(newOffice.getName())); - Assertions.assertTrue(newOffice.getOpeningDate().isEqual(LocalDate.of(2007, 7, 2))); + Assertions.assertTrue(DateUtils.isEqual(newOffice.getOpeningDate(), LocalDate.of(2007, 7, 2))); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java index d7a844e2f..8f069ccf1 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java @@ -41,6 +41,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.fineract.client.models.PutJobsJobIDRequest; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.client.IntegrationTest; import org.hamcrest.MatcherAssert; import org.slf4j.Logger; @@ -185,8 +186,7 @@ public class SchedulerJobHelper extends IntegrationTest { } Instant jobRunStartTime = df.parse(jobRunStartText, Instant::from); Instant jobRunEndTime = df.parse(jobRunEndText, Instant::from); - return (jobRunStartTime.equals(beforeExecuteTime) || jobRunStartTime.isAfter(beforeExecuteTime)) - && (jobRunEndTime.equals(jobRunStartTime) || jobRunEndTime.isAfter(jobRunStartTime)); + return !jobRunStartTime.isBefore(beforeExecuteTime) && !jobRunEndTime.isBefore(jobRunStartTime); }); // Verify triggerType @@ -206,7 +206,7 @@ public class SchedulerJobHelper extends IntegrationTest { public void fastForwardTime(LocalDate lastBusinessDateBeforeFastForward, LocalDate dateToFastForward, String jobName, ResponseSpecification responseSpec) { - while (lastBusinessDateBeforeFastForward.isBefore(dateToFastForward)) { + while (DateUtils.isBefore(lastBusinessDateBeforeFastForward, dateToFastForward)) { BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, lastBusinessDateBeforeFastForward); executeAndAwaitJob(jobName); lastBusinessDateBeforeFastForward = lastBusinessDateBeforeFastForward.plusDays(1); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java index ca797bdc4..3dab92329 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java @@ -83,6 +83,7 @@ import org.apache.fineract.client.models.PutLoansLoanIdChargesChargeIdResponse; import org.apache.fineract.client.models.PutLoansLoanIdRequest; import org.apache.fineract.client.models.PutLoansLoanIdResponse; import org.apache.fineract.client.util.JSON; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.client.IntegrationTest; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.PaymentTypeHelper; @@ -1437,7 +1438,7 @@ public class LoanTransactionHelper extends IntegrationTest { LocalDate accrualEntryDate = LocalDate.of(accrualEntryDateAsArray.get(0), accrualEntryDateAsArray.get(1), accrualEntryDateAsArray.get(2)); - if (transactionDate.isEqual(accrualEntryDate)) { + if (DateUtils.isEqual(transactionDate, accrualEntryDate)) { isTransactionFound = true; assertEquals(interestPortion, Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))), "Mismatch in transaction amounts"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/datatable/DatatableAdvancedQueryTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/datatable/DatatableAdvancedQueryTest.java index 54f1acc43..337c64452 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/datatable/DatatableAdvancedQueryTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/datatable/DatatableAdvancedQueryTest.java @@ -48,7 +48,6 @@ import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashMap; @@ -122,8 +121,7 @@ public class DatatableAdvancedQueryTest { @Test public void testDatatableAdvancedQuery() { String datatable = createAndVerifyDatatable(SAVINGS_TRANSACTION_APP_TABLE_NAME, null, false); - - LocalDate today = LocalDate.now(ZoneId.systemDefault()); + LocalDate today = Utils.getLocalDateOfTenant(); String todayS = DateUtils.format(today, SAVINGS_DATE_FORMAT); LocalDate yesterday = today.minus(1, ChronoUnit.DAYS); String yesterdayS = DateUtils.format(yesterday, SAVINGS_DATE_FORMAT); @@ -207,7 +205,7 @@ public class DatatableAdvancedQueryTest { public void testApptableWithDatatableAdvancedQuery() { String datatable = createAndVerifyDatatable(SAVINGS_TRANSACTION_APP_TABLE_NAME, null, false); - LocalDate today = LocalDate.now(ZoneId.systemDefault()); + LocalDate today = Utils.getLocalDateOfTenant(); String todayS = DateUtils.format(today, SAVINGS_DATE_FORMAT); LocalDate yesterday = today.minus(1, ChronoUnit.DAYS); String yesterdayS = DateUtils.format(yesterday, SAVINGS_DATE_FORMAT);