From 71afd6dead998d0b9ebdb44868ee76f710542a3d Mon Sep 17 00:00:00 2001 From: jmarta Date: Fri, 13 Oct 2023 00:54:23 +0200 Subject: [PATCH] FINERACT-1955: Timezone handling of Savings account --- .../core/domain/AbstractAuditableCustom.java | 4 +- ...bstractAuditableWithUTCDateTimeCustom.java | 31 +- .../core/service/DateUtils.java | 213 +++++++- .../portfolio/group/domain/Group.java | 42 +- .../data/SavingsAccountTransactionData.java | 24 +- .../savings/domain/SavingsHelper.java | 13 +- .../interest/CompoundInterestHelper.java | 3 +- .../domain/interest/EndOfDayBalance.java | 9 +- .../domain/interest/PostingPeriod.java | 32 +- ...untTransactionDetailsForPostingPeriod.java | 8 +- .../portfolio/loanaccount/domain/Loan.java | 4 +- .../loanaccount/domain/LoanTransaction.java | 1 + .../campaigns/sms/domain/SmsCampaign.java | 53 +- .../service/SmsCampaignDomainServiceImpl.java | 2 +- ...msCampaignWritePlatformServiceJpaImpl.java | 61 +-- .../core/auditing/CustomAuditingHandler.java | 2 +- .../core/auditing/CustomDateTimeProvider.java | 11 +- .../data/InteropAccountData.java | 6 +- .../data/InteropTransactionData.java | 4 +- .../domain/InteropIdentifier.java | 10 +- .../service/InteropServiceImpl.java | 27 +- ...WritePlatformServiceJpaRepositoryImpl.java | 7 +- .../domain/InterestRateChart.java | 11 +- .../domain/InterestRateChartFields.java | 28 +- .../service/GuarantorDomainServiceImpl.java | 2 +- ...ritePlatformServiceJpaRepositoryIImpl.java | 6 +- .../DepositAccountInterestRateChartData.java | 4 +- .../data/SavingsAccountTransactionDTO.java | 31 +- ...avingsAccountTransactionDataValidator.java | 14 +- .../domain/DepositAccountAssembler.java | 15 +- .../domain/DepositAccountDomainService.java | 13 +- .../DepositAccountDomainServiceJpa.java | 58 +-- .../DepositAccountInterestRateChart.java | 8 +- .../DepositAccountOnHoldTransaction.java | 46 +- .../DepositAccountTermAndPreClosure.java | 4 +- .../savings/domain/FixedDepositAccount.java | 59 +-- .../savings/domain/FixedDepositProduct.java | 4 +- .../domain/RecurringDepositAccount.java | 104 ++-- .../RecurringDepositScheduleInstallment.java | 51 +- .../savings/domain/SavingsAccount.java | 425 ++++++---------- .../domain/SavingsAccountAssembler.java | 7 +- .../savings/domain/SavingsAccountCharge.java | 39 +- .../domain/SavingsAccountDomainService.java | 4 +- .../SavingsAccountDomainServiceJpa.java | 33 +- .../savings/domain/SavingsAccountSummary.java | 4 +- .../domain/SavingsAccountTransaction.java | 480 +++++++++--------- .../SavingsAccountTransactionComparator.java | 24 +- ...vingsAccountTransactionDataComparator.java | 25 +- .../SavingsOfficerAssignmentHistory.java | 73 ++- .../GenerateRdScheduleConfig.java | 5 +- .../GenerateRdScheduleTasklet.java | 57 +-- ...DepositAccountReadPlatformServiceImpl.java | 6 +- ...WritePlatformServiceJpaRepositoryImpl.java | 115 ++--- ...WritePlatformServiceJpaRepositoryImpl.java | 12 +- ...sAccountChargeReadPlatformServiceImpl.java | 1 - ...ingsAccountInterestPostingServiceImpl.java | 39 +- ...SavingsAccountReadPlatformServiceImpl.java | 34 +- ...WritePlatformServiceJpaRepositoryImpl.java | 108 ++-- ...WritePlatformServiceJpaRepositoryImpl.java | 10 +- .../SavingsSchedularInterestPoster.java | 108 ++-- ...sAccountTransactionsSearchServiceImpl.java | 3 +- .../db/changelog/tenant/changelog-tenant.xml | 1 + .../tenant/parts/0128_savings_audit.xml | 266 ++++++++++ .../auditing/CustomAuditingHandlerTest.java | 8 +- .../auditing/CustomDateTimeProviderTest.java | 8 +- .../core/service/DateUtilsTest.java | 10 +- .../ClientSavingsIntegrationTest.java | 2 +- ...ountTransactionsSearchIntegrationTest.java | 3 +- .../integrationtests/SavingsAccountsTest.java | 8 +- ...SavingsInterestPostingIntegrationTest.java | 6 +- ...ingsInterestPostingJobIntegrationTest.java | 10 +- .../SchedulerJobsTestResults.java | 3 +- .../integrationtests/common/Utils.java | 14 + .../common/organisation/CampaignsHelper.java | 5 +- 74 files changed, 1567 insertions(+), 1414 deletions(-) create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0128_savings_audit.xml diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableCustom.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableCustom.java index 35ea048b39f..e733975eb8e 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableCustom.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableCustom.java @@ -67,7 +67,7 @@ public void setCreatedBy(final Long createdBy) { @Override public Optional getCreatedDate() { - return null == this.createdDate ? Optional.empty() : Optional.of(this.createdDate); + return Optional.ofNullable(this.createdDate); } @Override @@ -87,7 +87,7 @@ public void setLastModifiedBy(final Long lastModifiedBy) { @Override public Optional getLastModifiedDate() { - return null == this.lastModifiedDate ? Optional.empty() : Optional.of(this.lastModifiedDate); + return Optional.ofNullable(this.lastModifiedDate); } @Override diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableWithUTCDateTimeCustom.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableWithUTCDateTimeCustom.java index dec09e6ee74..55beda888e5 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableWithUTCDateTimeCustom.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractAuditableWithUTCDateTimeCustom.java @@ -25,8 +25,10 @@ import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; +import jakarta.validation.constraints.NotNull; import java.time.OffsetDateTime; import java.util.Optional; +import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -44,7 +46,7 @@ @MappedSuperclass @Getter @Setter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public abstract class AbstractAuditableWithUTCDateTimeCustom extends AbstractPersistableCustom implements Auditable { @@ -67,33 +69,36 @@ public abstract class AbstractAuditableWithUTCDateTimeCustom extends AbstractPer private OffsetDateTime lastModifiedDate; @Override + @NotNull public Optional getCreatedBy() { return Optional.ofNullable(this.createdBy); } @Override + @NotNull public Optional getCreatedDate() { - if (this.createdDate == null) { - return Optional.empty(); - } else { - return Optional.of(this.createdDate - .withOffsetSameInstant(DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(this.createdDate.toInstant()))); - } + return Optional.ofNullable(createdDate); + } + + @NotNull + public OffsetDateTime getCreatedDateTime() { + return getCreatedDate().orElseGet(DateUtils::getAuditOffsetDateTime); } @Override + @NotNull public Optional getLastModifiedBy() { return Optional.ofNullable(this.lastModifiedBy); } @Override + @NotNull public Optional getLastModifiedDate() { - if (this.lastModifiedDate == null) { - return Optional.empty(); - } else { - return Optional.of(this.lastModifiedDate - .withOffsetSameInstant(DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(this.lastModifiedDate.toInstant()))); - } + return Optional.ofNullable(lastModifiedDate); } + @NotNull + public OffsetDateTime getLastModifiedDateTime() { + return getLastModifiedDate().orElseGet(DateUtils::getAuditOffsetDateTime); + } } 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 1056bde387b..ca45f22d17b 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 @@ -20,6 +20,7 @@ import static java.time.temporal.ChronoUnit.DAYS; +import jakarta.validation.constraints.NotNull; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.OffsetDateTime; @@ -33,7 +34,6 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; -import org.jetbrains.annotations.NotNull; public final class DateUtils { @@ -46,6 +46,8 @@ private DateUtils() { } + // DateTime + public static ZoneId getSystemZoneId() { return ZoneId.systemDefault(); } @@ -56,27 +58,38 @@ public static ZoneId getDateTimeZoneOfTenant() { } public static LocalDate getLocalDateOfTenant() { - final ZoneId zone = getDateTimeZoneOfTenant(); - return LocalDate.now(zone); + return LocalDate.now(getDateTimeZoneOfTenant()); } public static LocalDateTime getLocalDateTimeOfTenant() { - final ZoneId zone = getDateTimeZoneOfTenant(); - return LocalDateTime.now(zone).truncatedTo(ChronoUnit.SECONDS); + return getLocalDateTimeOfTenant(null); } - public static OffsetDateTime getOffsetDateTimeOfTenant() { - final ZoneId zone = getDateTimeZoneOfTenant(); - return OffsetDateTime.now(zone).truncatedTo(ChronoUnit.SECONDS); + public static LocalDateTime getLocalDateTimeOfTenant(ChronoUnit truncate) { + LocalDateTime now = LocalDateTime.now(getDateTimeZoneOfTenant()); + return truncate == null ? now : now.truncatedTo(truncate); } public static OffsetDateTime getOffsetDateTimeOfTenantWithMostPrecision() { - final ZoneId zone = getDateTimeZoneOfTenant(); - return OffsetDateTime.now(zone); + return getOffsetDateTimeOfTenant(null); + } + + public static OffsetDateTime getOffsetDateTimeOfTenant() { + return getOffsetDateTimeOfTenant(null); + } + + public static OffsetDateTime getOffsetDateTimeOfTenant(ChronoUnit truncate) { + OffsetDateTime now = OffsetDateTime.now(getDateTimeZoneOfTenant()); + return truncate == null ? now : now.truncatedTo(truncate); } public static LocalDateTime getLocalDateTimeOfSystem() { - return LocalDateTime.now(ZoneId.systemDefault()).truncatedTo(ChronoUnit.SECONDS); + return getLocalDateTimeOfSystem(null); + } + + public static LocalDateTime getLocalDateTimeOfSystem(ChronoUnit truncate) { + LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault()); + return truncate == null ? now : now.truncatedTo(truncate); } public static LocalDateTime getAuditLocalDateTime() { @@ -87,22 +100,176 @@ public static OffsetDateTime getAuditOffsetDateTime() { return OffsetDateTime.now(ZoneOffset.UTC); } - public static boolean isDateInTheFuture(final LocalDate localDate) { - return localDate.isAfter(getBusinessLocalDate()); + public static int compare(LocalDateTime first, LocalDateTime second) { + return compare(first, second, null); } - public static LocalDate getBusinessLocalDate() { - return ThreadLocalContextUtil.getBusinessDate(); + public static int compare(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) { + if (first == null) { + return second == null ? 0 : -1; + } + if (second == null) { + return 1; + } + return truncate == null ? first.compareTo(second) : first.truncatedTo(truncate).compareTo(second.truncatedTo(truncate)); } - public static long getDifferenceInDays(final LocalDate localDateBefore, final LocalDate localDateAfter) { - return DAYS.between(localDateBefore, localDateAfter); + public static boolean isEqual(LocalDateTime first, LocalDateTime second) { + return isEqual(first, second, null); + } + + public static boolean isEqual(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) { + return compare(first, second, truncate) == 0; + } + + public static boolean isEqualTenantDateTime(LocalDateTime dateTime) { + return isEqualTenantDateTime(dateTime, null); + } + + public static boolean isEqualTenantDateTime(LocalDateTime dateTime, ChronoUnit truncate) { + return isEqual(dateTime, getLocalDateTimeOfTenant(), truncate); + } + + public static boolean isEqualSystemDateTime(LocalDateTime dateTime) { + return isEqualSystemDateTime(dateTime, null); + } + + public static boolean isEqualSystemDateTime(LocalDateTime dateTime, ChronoUnit truncate) { + return isEqual(dateTime, getLocalDateTimeOfSystem(), truncate); + } + + public static boolean isBefore(LocalDateTime first, LocalDateTime second) { + return isBefore(first, second, null); + } + + public static boolean isBefore(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) { + return compare(first, second, truncate) < 0; + } + + public static boolean isBeforeTenantDateTime(LocalDateTime dateTime) { + return isBeforeTenantDateTime(dateTime, null); + } + + public static boolean isBeforeTenantDateTime(LocalDateTime dateTime, ChronoUnit truncate) { + return isBefore(dateTime, getLocalDateTimeOfTenant(), truncate); + } + + public static boolean isBeforeSystemDateTime(LocalDateTime dateTime) { + return isBeforeSystemDateTime(dateTime, null); + } + + public static boolean isBeforeSystemDateTime(LocalDateTime dateTime, ChronoUnit truncate) { + return isBefore(dateTime, getLocalDateTimeOfSystem(), truncate); + } + + public static boolean isAfter(LocalDateTime first, LocalDateTime second) { + return isAfter(first, second, null); + } + + public static boolean isAfter(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) { + return compare(first, second, truncate) > 0; + } + + public static boolean isAfterTenantDateTime(LocalDateTime dateTime) { + return isAfterTenantDateTime(dateTime, null); + } + + public static boolean isAfterTenantDateTime(LocalDateTime dateTime, ChronoUnit truncate) { + return isAfter(dateTime, getLocalDateTimeOfTenant(), truncate); + } + + public static boolean isAfterSystemDateTime(LocalDateTime dateTime) { + return isAfterSystemDateTime(dateTime, null); + } + + public static boolean isAfterSystemDateTime(LocalDateTime dateTime, ChronoUnit truncate) { + return isAfter(dateTime, getLocalDateTimeOfSystem(), truncate); + } + + public static int compare(OffsetDateTime first, OffsetDateTime second) { + return compare(first, second, null); + } + + public static int compare(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) { + if (first == null) { + return second == null ? 0 : -1; + } + if (second == null) { + return 1; + } + return truncate == null ? first.compareTo(second) : first.truncatedTo(truncate).compareTo(second.truncatedTo(truncate)); + } + + public static boolean isEqual(OffsetDateTime first, OffsetDateTime second) { + return isEqual(first, second, null); + } + + public static boolean isEqual(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) { + return compare(first, second, truncate) == 0; + } + + public static boolean isEqualTenantDateTime(OffsetDateTime dateTime) { + return isEqualTenantDateTime(dateTime, null); + } + + public static boolean isEqualTenantDateTime(OffsetDateTime dateTime, ChronoUnit truncate) { + return isEqual(dateTime, getOffsetDateTimeOfTenant(), truncate); + } + + public static boolean isBefore(OffsetDateTime first, OffsetDateTime second) { + return isBefore(first, second, null); + } + + public static boolean isBefore(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) { + return compare(first, second, truncate) < 0; + } + + public static boolean isBeforeTenantDateTime(OffsetDateTime dateTime) { + return isBeforeTenantDateTime(dateTime, null); + } + + public static boolean isBeforeTenantDateTime(OffsetDateTime dateTime, ChronoUnit truncate) { + return isBefore(dateTime, getOffsetDateTimeOfTenant(), truncate); + } + + public static boolean isAfter(OffsetDateTime first, OffsetDateTime second) { + return isAfter(first, second, null); + } + + public static boolean isAfter(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) { + return compare(first, second, truncate) > 0; + } + + public static boolean isAfterTenantDateTime(OffsetDateTime dateTime) { + return isAfterTenantDateTime(dateTime, null); + } + + public static boolean isAfterTenantDateTime(OffsetDateTime dateTime, ChronoUnit truncate) { + return isAfter(dateTime, getOffsetDateTimeOfTenant(), truncate); + } + + // Date + + public static LocalDate getBusinessLocalDate() { + return ThreadLocalContextUtil.getBusinessDate(); } public static int compareToBusinessDate(LocalDate date) { return compare(date, getBusinessLocalDate()); } + public static boolean isEqualTenantDate(LocalDate date) { + return isEqual(date, getLocalDateOfTenant()); + } + + public static boolean isBeforeTenantDate(LocalDate date) { + return isBefore(date, getLocalDateOfTenant()); + } + + public static boolean isAfterTenantDate(LocalDate date) { + return isAfter(date, getLocalDateOfTenant()); + } + public static boolean isEqualBusinessDate(LocalDate date) { return isEqual(date, getBusinessLocalDate()); } @@ -115,8 +282,12 @@ public static boolean isAfterBusinessDate(LocalDate date) { return isAfter(date, getBusinessLocalDate()); } + public static boolean isDateInTheFuture(final LocalDate localDate) { + return isAfterBusinessDate(localDate); + } + public static int compare(LocalDate first, LocalDate second) { - return first == null ? (second == null ? 0 : -1) : first.compareTo(second); + return first == null ? (second == null ? 0 : -1) : (second == null ? 1 : first.compareTo(second)); } public static boolean isEqual(LocalDate first, LocalDate second) { @@ -131,6 +302,12 @@ public static boolean isAfter(LocalDate first, LocalDate second) { return first != null && (second == null || first.isAfter(second)); } + public static long getDifferenceInDays(final LocalDate localDateBefore, final LocalDate localDateAfter) { + return DAYS.between(localDateBefore, localDateAfter); + } + + // Parse, format + public static LocalDate parseLocalDate(String stringDate) { return parseLocalDate(stringDate, null); } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java index 37a16d4f523..84d73c8e1a0 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java @@ -259,7 +259,7 @@ private void setActivationDate(final LocalDate activationDate, final AppUser log } public boolean isActivatedAfter(final LocalDate submittedOn) { - return getActivationLocalDate().isAfter(submittedOn); + return DateUtils.isAfter(getActivationDate(), submittedOn); } public boolean isNotActive() { @@ -267,11 +267,7 @@ public boolean isNotActive() { } public boolean isActive() { - return this.status != null ? GroupingTypeStatus.fromInt(this.status).isActive() : false; - } - - private boolean isDateInTheFuture(final LocalDate localDate) { - return localDate.isAfter(DateUtils.getBusinessLocalDate()); + return this.status != null && GroupingTypeStatus.fromInt(this.status).isActive(); } public boolean isNotPending() { @@ -316,7 +312,7 @@ public Map update(final JsonCommand command) { final String dateFormatAsInput = command.dateFormat(); final String localeAsInput = command.locale(); - if (command.isChangeInLocalDateParameterNamed(GroupingTypesApiConstants.activationDateParamName, getActivationLocalDate())) { + if (command.isChangeInLocalDateParameterNamed(GroupingTypesApiConstants.activationDateParamName, getActivationDate())) { final String valueAsInput = command.stringValueOfParameterNamed(GroupingTypesApiConstants.activationDateParamName); actualChanges.put(GroupingTypesApiConstants.activationDateParamName, valueAsInput); actualChanges.put(GroupingTypesApiConstants.dateFormatParamName, dateFormatAsInput); @@ -347,7 +343,7 @@ public LocalDate getSubmittedOnDate() { return this.submittedOnDate; } - public LocalDate getActivationLocalDate() { + public LocalDate getActivationDate() { return this.activationDate; } @@ -494,7 +490,7 @@ public boolean isChildClient(final Long clientId) { } public boolean isChildGroup() { - return this.parent == null ? false : true; + return this.parent != null; } @@ -503,18 +499,17 @@ public boolean isClosed() { } public void close(final AppUser currentUser, final CodeValue closureReason, final LocalDate closureDate) { - if (isClosed()) { final String errorMessage = "Group with identifier " + getId() + " is alread closed."; throw new InvalidGroupStateTransitionException(this.groupLevel.getLevelName(), "close", "already.closed", errorMessage, getId()); } - if (isNotPending() && getActivationLocalDate().isAfter(closureDate)) { + if (isNotPending() && DateUtils.isAfter(getActivationDate(), closureDate)) { final String errorMessage = "The Group closure Date " + closureDate + " cannot be before the group Activation Date " - + getActivationLocalDate() + "."; + + getActivationDate() + "."; throw new InvalidGroupStateTransitionException(this.groupLevel.getLevelName(), "close", - "date.cannot.before.group.actvation.date", errorMessage, closureDate, getActivationLocalDate()); + "date.cannot.before.group.actvation.date", errorMessage, closureDate, getActivationDate()); } this.closureReason = closureReason; @@ -644,9 +639,7 @@ public Set getActiveClientMembers() { } private void validateActivationDate(final List dataValidationErrors) { - - if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) { - + if (getSubmittedOnDate() != null && DateUtils.isDateInTheFuture(getSubmittedOnDate())) { final String defaultUserMessage = "Submitted on date cannot be in the future."; final String globalisationMessageCode = "error.msg.group.submittedOnDate.in.the.future"; final ApiParameterError error = ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage, @@ -654,31 +647,26 @@ private void validateActivationDate(final List dataValidation dataValidationErrors.add(error); } - - if (getActivationLocalDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getActivationLocalDate())) { - + if (getActivationDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getActivationDate())) { final String defaultUserMessage = "Submitted on date cannot be after the activation date"; final ApiParameterError error = ApiParameterError.parameterError("error.msg.group.submittedOnDate.after.activation.date", defaultUserMessage, GroupingTypesApiConstants.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - - if (getActivationLocalDate() != null && isDateInTheFuture(getActivationLocalDate())) { - + if (getActivationDate() != null && DateUtils.isDateInTheFuture(getActivationDate())) { final String defaultUserMessage = "Activation date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.group.activationDate.in.the.future", - defaultUserMessage, GroupingTypesApiConstants.activationDateParamName, getActivationLocalDate()); + defaultUserMessage, GroupingTypesApiConstants.activationDateParamName, getActivationDate()); dataValidationErrors.add(error); } - - if (getActivationLocalDate() != null) { - if (this.office.isOpeningDateAfter(getActivationLocalDate())) { + if (getActivationDate() != null) { + if (this.office.isOpeningDateAfter(getActivationDate())) { final String defaultUserMessage = "Activation date cannot be a date before the office opening date."; final ApiParameterError error = ApiParameterError.parameterError( "error.msg.group.activationDate.cannot.be.before.office.activation.date", defaultUserMessage, - GroupingTypesApiConstants.activationDateParamName, getActivationLocalDate()); + GroupingTypesApiConstants.activationDateParamName, getActivationDate()); dataValidationErrors.add(error); } } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionData.java index 0ff25943d98..9a06951b51c 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionData.java @@ -402,7 +402,7 @@ public boolean isChargeTransactionAndNotReversed() { } public boolean occursOn(final LocalDate occursOnDate) { - return getTransactionDate().isEqual(occursOnDate); + return DateUtils.isEqual(occursOnDate, getTransactionDate()); } public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy, @@ -416,7 +416,7 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi LocalDate balanceStartDate = getTransactionDate(); LocalDate balanceEndDate = getEndOfBalanceLocalDate(); - if (boundedBy.startDate().isAfter(balanceStartDate)) { + if (DateUtils.isAfter(boundedBy.startDate(), balanceStartDate)) { balanceStartDate = boundedBy.startDate(); final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -432,7 +432,7 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi } } - if (balanceEndDate.isAfter(boundedBy.endDate())) { + if (DateUtils.isAfter(balanceEndDate, boundedBy.endDate())) { balanceEndDate = boundedBy.endDate(); final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -479,7 +479,7 @@ public Set getSavingsAccountChargesPaid() { public void updateCumulativeBalanceAndDates(final MonetaryCurrency currency, final LocalDate endOfBalanceDate) { // balance end date should not be before transaction date - if (endOfBalanceDate != null && endOfBalanceDate.isBefore(this.transactionDate)) { + if (endOfBalanceDate != null && DateUtils.isBefore(endOfBalanceDate, this.transactionDate)) { this.balanceEndDate = this.transactionDate; } else if (endOfBalanceDate != null) { this.balanceEndDate = endOfBalanceDate; @@ -501,7 +501,7 @@ public boolean isFeeChargeAndNotReversed() { public boolean isFeeCharge() { final SavingsAccountChargesPaidByData chargePaidBy = getSavingsAccountChargePaidBy(); - return (isPayCharge() && chargePaidBy != null) ? chargePaidBy.isFeeCharge() : false; + return isPayCharge() && chargePaidBy != null && chargePaidBy.isFeeCharge(); } public void setChargesPaidByData(final SavingsAccountChargesPaidByData savingsAccountChargesPaidByData) { @@ -518,7 +518,7 @@ public boolean isPenaltyChargeAndNotReversed() { public boolean isPenaltyCharge() { final SavingsAccountChargesPaidByData chargePaidBy = getSavingsAccountChargePaidBy(); - return (isPayCharge() && chargePaidBy != null) ? chargePaidBy.isPenaltyCharge() : false; + return isPayCharge() && chargePaidBy != null && chargePaidBy.isPenaltyCharge(); } public boolean isWaiveFeeChargeAndNotReversed() { @@ -527,7 +527,7 @@ public boolean isWaiveFeeChargeAndNotReversed() { public boolean isWaiveFeeCharge() { final SavingsAccountChargesPaidByData chargePaidBy = getSavingsAccountChargePaidBy(); - return (isWaiveCharge() && chargePaidBy != null) ? chargePaidBy.isFeeCharge() : false; + return isWaiveCharge() && chargePaidBy != null && chargePaidBy.isFeeCharge(); } public boolean isWaiveCharge() { @@ -540,7 +540,7 @@ public boolean isWaivePenaltyChargeAndNotReversed() { public boolean isWaivePenaltyCharge() { final SavingsAccountChargesPaidByData chargePaidBy = getSavingsAccountChargePaidBy(); - return (isWaiveCharge() && chargePaidBy != null) ? chargePaidBy.isPenaltyCharge() : false; + return isWaiveCharge() && chargePaidBy != null && chargePaidBy.isPenaltyCharge(); } private SavingsAccountChargesPaidByData getSavingsAccountChargePaidBy() { @@ -572,7 +572,7 @@ public Map toMapData(final CurrencyData currencyData, final Long thisTransactionData.put("id", getId()); thisTransactionData.put("officeId", officeId); thisTransactionData.put("type", transactionType); - thisTransactionData.put("reversed", Boolean.valueOf(isReversed())); + thisTransactionData.put("reversed", isReversed()); thisTransactionData.put("date", getTransactionDate()); thisTransactionData.put("currency", currencyData); thisTransactionData.put("amount", this.amount); @@ -582,10 +582,8 @@ public Map toMapData(final CurrencyData currencyData, final Long thisTransactionData.put("paymentTypeId", this.paymentDetailData.getPaymentType().getId()); } - /*** - * Sending data in a map, though in savings we currently expect a transaction to always repay a single charge - * (or may repay a part of a single charge too) - ***/ + // Sending data in a map, though in savings we currently expect a transaction to always repay a single charge + // (or may repay a part of a single charge too) if (!this.chargesPaidByData.isEmpty()) { final List> savingsChargesPaidData = new ArrayList<>(); for (final SavingsAccountChargesPaidByData chargePaidBy : this.chargesPaidByData) { diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsHelper.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsHelper.java index 1fe4df28eb7..5e7a36e48ca 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsHelper.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsHelper.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.List; import org.apache.fineract.infrastructure.core.domain.LocalDateInterval; +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.account.service.AccountTransfersReadPlatformService; @@ -55,8 +56,7 @@ public List determineInterestPostingPeriods(final LocalDate s LocalDate periodEndDate = periodStartDate; LocalDate actualPeriodStartDate = periodStartDate; - while (!periodStartDate.isAfter(interestPostingUpToDate) && !periodEndDate.isAfter(interestPostingUpToDate)) { - + while (!DateUtils.isAfter(periodStartDate, interestPostingUpToDate) && !DateUtils.isAfter(periodEndDate, interestPostingUpToDate)) { final LocalDate interestPostingLocalDate = determineInterestPostingPeriodEndDateFrom(periodStartDate, postingPeriodType, interestPostingUpToDate, financialYearBeginningMonth); @@ -64,8 +64,7 @@ public List determineInterestPostingPeriods(final LocalDate s if (!postInterestAsOn.isEmpty()) { for (LocalDate transactiondate : postInterestAsOn) { - if (periodStartDate.isBefore(transactiondate) - && (periodEndDate.isAfter(transactiondate) || periodEndDate.isEqual(transactiondate))) { + if (DateUtils.isAfter(transactiondate, periodStartDate) && !DateUtils.isAfter(transactiondate, periodEndDate)) { periodEndDate = transactiondate.minusDays(1); actualPeriodStartDate = periodEndDate; break; @@ -75,7 +74,7 @@ public List determineInterestPostingPeriods(final LocalDate s postingPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate)); - if (actualPeriodStartDate.isEqual(periodEndDate)) { + if (DateUtils.isEqual(actualPeriodStartDate, periodEndDate)) { periodEndDate = actualPeriodStartDate.plusDays(1); periodStartDate = actualPeriodStartDate.plusDays(1); } else { @@ -128,7 +127,7 @@ private LocalDate determineInterestPostingPeriodEndDateFrom(final LocalDate peri break; case QUATERLY: for (LocalDate quarterlyDate : quarterlyDates) { - if (quarterlyDate.isAfter(periodStartDate)) { + if (DateUtils.isAfter(quarterlyDate, periodStartDate)) { periodEndDate = quarterlyDate; isEndDateSet = true; break; @@ -141,7 +140,7 @@ private LocalDate determineInterestPostingPeriodEndDateFrom(final LocalDate peri break; case BIANNUAL: for (LocalDate biannualDate : biannualDates) { - if (biannualDate.isAfter(periodStartDate)) { + if (DateUtils.isAfter(biannualDate, periodStartDate)) { periodEndDate = biannualDate; isEndDateSet = true; break; diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/CompoundInterestHelper.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/CompoundInterestHelper.java index 3d460fef175..4b918c0198a 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/CompoundInterestHelper.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/CompoundInterestHelper.java @@ -21,6 +21,7 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @@ -59,7 +60,7 @@ public Money calculateInterestForAllPostingPeriods(final MonetaryCurrency curren // account and if already transfered then it includes in interest // calculation. if (!(postingPeriod.isInterestTransfered() || !interestTransferEnabled - || (lockUntil != null && !postingPeriod.dateOfPostingTransaction().isAfter(lockUntil)))) { + || (lockUntil != null && !DateUtils.isAfter(postingPeriod.dateOfPostingTransaction(), lockUntil)))) { compoundInterestValues.setcompoundedInterest(BigDecimal.ZERO); } } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/EndOfDayBalance.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/EndOfDayBalance.java index 58b51995f6d..ce821427c42 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/EndOfDayBalance.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/EndOfDayBalance.java @@ -22,6 +22,7 @@ import java.math.MathContext; import java.time.LocalDate; import org.apache.fineract.infrastructure.core.domain.LocalDateInterval; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.organisation.monetary.domain.MoneyHelper; @@ -136,7 +137,6 @@ public BigDecimal calculateInterestOnBalanceAndInterest(final BigDecimal interes * @return */ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, final LocalDate upToInterestCalculationDate) { - Money startingBalance = this.openingBalance; LocalDate balanceStartDate = this.date; @@ -144,7 +144,7 @@ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, f int daysOfBalance = this.numberOfDays; - if (this.date.isBefore(compoundingPeriodInterval.startDate())) { + if (DateUtils.isBefore(this.date, compoundingPeriodInterval.startDate())) { balanceStartDate = compoundingPeriodInterval.startDate(); startingBalance = this.endOfDayBalance; final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, oldBalanceEndDate); @@ -152,12 +152,12 @@ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, f } LocalDate balanceEndDate = balanceStartDate.plusDays(daysOfBalance - 1); - if (balanceEndDate.isAfter(compoundingPeriodInterval.endDate())) { + if (DateUtils.isAfter(balanceEndDate, compoundingPeriodInterval.endDate())) { balanceEndDate = compoundingPeriodInterval.endDate(); final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate); daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate(); } - if (balanceEndDate.isAfter(upToInterestCalculationDate)) { + if (DateUtils.isAfter(balanceEndDate, upToInterestCalculationDate)) { balanceEndDate = upToInterestCalculationDate; final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate); daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate(); @@ -167,7 +167,6 @@ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, f } public boolean contains(final LocalDateInterval compoundingPeriodInterval) { - final LocalDate balanceUpToDate = this.date.plusDays(this.numberOfDays - 1); final LocalDateInterval balanceInterval = LocalDateInterval.create(this.date, balanceUpToDate); diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java index f65b7ce6020..f0bce2b1277 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java @@ -132,7 +132,7 @@ public static PostingPeriod createFrom(final LocalDateInterval periodInterval, f LocalDate balanceEndDate = periodInterval.endDate(); Integer numberOfDaysOfBalance = periodInterval.daysInPeriodInclusiveOfEndDate(); - if (balanceEndDate.isAfter(upToInterestCalculationDate)) { + if (DateUtils.isAfter(balanceEndDate, upToInterestCalculationDate)) { balanceEndDate = upToInterestCalculationDate; final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -206,7 +206,7 @@ public static PostingPeriod createFromDTO(final LocalDateInterval periodInterval LocalDate balanceEndDate = periodInterval.endDate(); Integer numberOfDaysOfBalance = periodInterval.daysInPeriodInclusiveOfEndDate(); - if (balanceEndDate.isAfter(upToInterestCalculationDate)) { + if (DateUtils.isAfter(balanceEndDate, upToInterestCalculationDate)) { balanceEndDate = upToInterestCalculationDate; final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -328,23 +328,21 @@ private static List compoundingPeriodsInPostingPeriod(final L compoundingPeriods.add(compoundingPeriod); break; case MONTHLY: - final LocalDate postingPeriodEndDate = postingPeriodInterval.endDate(); LocalDate periodStartDate = postingPeriodInterval.startDate(); LocalDate periodEndDate = periodStartDate; - while (!periodStartDate.isAfter(postingPeriodEndDate) && !periodEndDate.isAfter(postingPeriodEndDate)) { - + while (!DateUtils.isAfter(periodStartDate, postingPeriodEndDate) + && !DateUtils.isAfter(periodEndDate, postingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth); - if (periodEndDate.isAfter(postingPeriodEndDate)) { + if (DateUtils.isAfter(periodEndDate, postingPeriodEndDate)) { periodEndDate = postingPeriodEndDate; } final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate); if (postingPeriodInterval.contains(compoundingPeriodInterval)) { - compoundingPeriod = MonthlyCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); @@ -364,17 +362,16 @@ private static List compoundingPeriodsInPostingPeriod(final L periodStartDate = postingPeriodInterval.startDate(); periodEndDate = periodStartDate; - while (!periodStartDate.isAfter(qPostingPeriodEndDate) && !periodEndDate.isAfter(qPostingPeriodEndDate)) { - + while (!DateUtils.isAfter(periodStartDate, qPostingPeriodEndDate) + && !DateUtils.isAfter(periodEndDate, qPostingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth); - if (periodEndDate.isAfter(qPostingPeriodEndDate)) { + if (DateUtils.isAfter(periodEndDate, qPostingPeriodEndDate)) { periodEndDate = qPostingPeriodEndDate; } final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate); if (postingPeriodInterval.contains(compoundingPeriodInterval)) { - compoundingPeriod = QuarterlyCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances, upToInterestCalculationDate); compoundingPeriods.add(compoundingPeriod); @@ -390,11 +387,11 @@ private static List compoundingPeriodsInPostingPeriod(final L periodStartDate = postingPeriodInterval.startDate(); periodEndDate = periodStartDate; - while (!periodStartDate.isAfter(bPostingPeriodEndDate) && !periodEndDate.isAfter(bPostingPeriodEndDate)) { - + while (!DateUtils.isAfter(periodStartDate, bPostingPeriodEndDate) + && !DateUtils.isAfter(periodEndDate, bPostingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth); - if (periodEndDate.isAfter(bPostingPeriodEndDate)) { + if (DateUtils.isAfter(periodEndDate, bPostingPeriodEndDate)) { periodEndDate = bPostingPeriodEndDate; } @@ -416,11 +413,12 @@ private static List compoundingPeriodsInPostingPeriod(final L periodStartDate = postingPeriodInterval.startDate(); periodEndDate = periodStartDate; - while (!periodStartDate.isAfter(aPostingPeriodEndDate) && !periodEndDate.isAfter(aPostingPeriodEndDate)) { + while (!DateUtils.isAfter(periodStartDate, aPostingPeriodEndDate) + && !DateUtils.isAfter(periodEndDate, aPostingPeriodEndDate)) { periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth); - if (periodEndDate.isAfter(aPostingPeriodEndDate)) { + if (DateUtils.isAfter(periodEndDate, aPostingPeriodEndDate)) { periodEndDate = aPostingPeriodEndDate; } @@ -483,7 +481,7 @@ private static LocalDate determineInterestPeriodEndDateFrom(final LocalDate peri case ANNUAL: periodEndDate = periodStartDate.withMonth(previousMonth); periodEndDate = periodEndDate.with(TemporalAdjusters.lastDayOfMonth()); - if (periodEndDate.isBefore(periodStartDate)) { + if (DateUtils.isBefore(periodEndDate, periodStartDate)) { periodEndDate = periodEndDate.plusYears(1); } break; diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/SavingsAccountTransactionDetailsForPostingPeriod.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/SavingsAccountTransactionDetailsForPostingPeriod.java index ce9a5465051..3a3145b377f 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/SavingsAccountTransactionDetailsForPostingPeriod.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/SavingsAccountTransactionDetailsForPostingPeriod.java @@ -23,6 +23,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.apache.fineract.infrastructure.core.domain.LocalDateInterval; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @@ -54,7 +55,7 @@ public boolean spansAnyPortionOf(final LocalDateInterval periodInterval) { } public boolean occursOn(final LocalDate occursOnDate) { - return getTransactionDate().isEqual(occursOnDate); + return DateUtils.isEqual(occursOnDate, getTransactionDate()); } public EndOfDayBalance toEndOfDayBalance(final Money openingBalance) { @@ -92,7 +93,6 @@ public EndOfDayBalance toEndOfDayBalance(final LocalDateInterval periodInterval, } public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy) { - final MonetaryCurrency currency = openingBalance.getCurrency(); Money endOfDayBalance = openingBalance.copy(); @@ -101,7 +101,7 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi LocalDate balanceStartDate = getTransactionDate(); LocalDate balanceEndDate = getEndOfBalanceDate(); - if (boundedBy.startDate().isAfter(balanceStartDate)) { + if (DateUtils.isAfter(boundedBy.startDate(), balanceStartDate)) { balanceStartDate = boundedBy.startDate(); final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -121,7 +121,7 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi } } - if (balanceEndDate.isAfter(boundedBy.endDate())) { + if (DateUtils.isAfter(balanceEndDate, boundedBy.endDate())) { balanceEndDate = boundedBy.endDate(); final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 6bd37070f1f..6dd9fc25efb 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -1609,7 +1609,7 @@ public Map loanApplicationModification(final JsonCommand command final String errorMessage = "The date on which a loan is submitted cannot be earlier than client's activation date."; throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.client.activation.date", errorMessage, getSubmittedOnDate()); - } else if (this.group != null && DateUtils.isBefore(getSubmittedOnDate(), this.group.getActivationLocalDate())) { + } else if (this.group != null && DateUtils.isBefore(getSubmittedOnDate(), this.group.getActivationDate())) { final String errorMessage = "The date on which a loan is submitted cannot be earlier than groups's activation date."; throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.group.activation.date", errorMessage, getSubmittedOnDate()); @@ -2124,7 +2124,7 @@ public void loanApplicationSubmittal(final LoanScheduleModel loanSchedule, final if (this.group != null && this.group.isActivatedAfter(submittedOn)) { final String errorMessage = "The date on which a loan is submitted cannot be earlier than groups's activation date."; throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.group.activation.date", errorMessage, submittedOn, - group.getActivationLocalDate()); + group.getActivationDate()); } if (DateUtils.isAfter(submittedOn, getExpectedDisbursedOnLocalDate())) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java index 185ed2d300f..ea458c8df93 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java @@ -850,6 +850,7 @@ public void manuallyAdjustedOrReversed() { this.manuallyAdjustedOrReversed = true; } + @Override public OffsetDateTime getCreatedDateTime() { return (this.getCreatedDate().isPresent() ? this.getCreatedDate().get() : DateUtils.getOffsetDateTimeOfTenantWithMostPrecision()); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/domain/SmsCampaign.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/domain/SmsCampaign.java index 0d3e8ec9b88..f230d0bc88a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/domain/SmsCampaign.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/domain/SmsCampaign.java @@ -119,7 +119,7 @@ public SmsCampaign() {} private SmsCampaign(final String campaignName, final Integer campaignType, final Integer triggerType, final Report businessRuleId, final Long providerId, final String paramValue, final String message, final LocalDate submittedOnDate, - final AppUser submittedBy, final String recurrence, final LocalDateTime localDateTime, final boolean isNotification) { + final AppUser submittedBy, final String recurrence, final LocalDateTime recurrenceStartDate, final boolean isNotification) { this.campaignName = campaignName; this.campaignType = campaignType; this.triggerType = SmsCampaignTriggerType.fromInt(triggerType).getValue(); @@ -131,18 +131,12 @@ private SmsCampaign(final String campaignName, final Integer campaignType, final this.submittedOnDate = submittedOnDate; this.submittedBy = submittedBy; this.recurrence = recurrence; - LocalDateTime recurrenceStartDate = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()); this.isVisible = true; - if (localDateTime != null) { - this.recurrenceStartDate = localDateTime; - } else { - this.recurrenceStartDate = recurrenceStartDate; - } + this.recurrenceStartDate = recurrenceStartDate; this.isNotification = isNotification; } public static SmsCampaign instance(final AppUser submittedBy, final Report report, final JsonCommand command) { - final String campaignName = command.stringValueOfParameterNamed(SmsCampaignValidator.campaignName); final Long campaignType = command.longValueOfParameterNamed(SmsCampaignValidator.campaignType); final Long triggerType = command.longValueOfParameterNamed(SmsCampaignValidator.triggerType); @@ -164,10 +158,11 @@ public static SmsCampaign instance(final AppUser submittedBy, final Report repor } String recurrence = null; - LocalDateTime recurrenceStartDate = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()); + LocalDateTime recurrenceStartDate = null; if (SmsCampaignTriggerType.fromInt(triggerType.intValue()).isSchedule()) { final Locale locale = command.extractLocale(); String dateTimeFormat; + recurrenceStartDate = DateUtils.getLocalDateTimeOfTenant(); if (command.hasParameter(SmsCampaignValidator.dateTimeFormat)) { dateTimeFormat = command.stringValueOfParameterNamed(SmsCampaignValidator.dateTimeFormat); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(dateTimeFormat).withLocale(locale); @@ -177,8 +172,6 @@ public static SmsCampaign instance(final AppUser submittedBy, final Report repor } recurrence = constructRecurrence(command); } - } else { - recurrenceStartDate = null; } return new SmsCampaign(campaignName, campaignType.intValue(), triggerType.intValue(), report, providerId, paramValue, message, @@ -186,7 +179,6 @@ public static SmsCampaign instance(final AppUser submittedBy, final Report repor } public Map update(JsonCommand command) { - final Map actualChanges = new LinkedHashMap<>(5); if (command.isChangeInStringParameterNamed(SmsCampaignValidator.campaignName, this.campaignName)) { @@ -255,7 +247,6 @@ public Map update(JsonCommand command) { } 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."; @@ -297,7 +288,6 @@ public void close(final AppUser currentUser, final DateTimeFormatter dateTimeFor } 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."; @@ -384,66 +374,55 @@ private void validateClosureDate() { } private void validateActivationDate(final List dataValidationErrors) { - - 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, SmsCampaignValidator.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.campaign.submittedOnDate.after.activation.date", defaultUserMessage, SmsCampaignValidator.submittedOnDateParamName, this.submittedOnDate); 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.campaign.activationDate.in.the.future", - defaultUserMessage, SmsCampaignValidator.activationDateParamName, getActivationLocalDate()); + defaultUserMessage, SmsCampaignValidator.activationDateParamName, getActivationDate()); dataValidationErrors.add(error); } - } private void validateReactivationDate(final List dataValidationErrors) { - 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.campaign.activationDate.in.the.future", - defaultUserMessage, SmsCampaignValidator.activationDateParamName, getActivationLocalDate()); + defaultUserMessage, SmsCampaignValidator.activationDateParamName, getActivationDate()); 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.campaign.submittedOnDate.after.activation.date", defaultUserMessage, SmsCampaignValidator.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, SmsCampaignValidator.submittedOnDateParamName, this.submittedOnDate); dataValidationErrors.add(error); } - } private void validateClosureDate(final List dataValidationErrors) { - if (getClosureDate() != null && isDateInTheFuture(getClosureDate())) { + if (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, SmsCampaignValidator.closureDateParamName, this.closureDate); @@ -461,14 +440,10 @@ public LocalDate getClosureDate() { return this.closureDate; } - public LocalDate getActivationLocalDate() { + public LocalDate getActivationDate() { return this.approvedOnDate; } - private boolean isDateInTheFuture(final LocalDate localDate) { - return localDate.isAfter(DateUtils.getBusinessLocalDate()); - } - public Report getBusinessRuleId() { return this.businessRuleId; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignDomainServiceImpl.java index fb02955dafa..582a4b4d859 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignDomainServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignDomainServiceImpl.java @@ -365,7 +365,7 @@ private HashMap processSavingsTransactionDataForSms(final Saving smsParams.put("depositAmount", savingsAccountTransaction.getAmount(savingsAccount.getCurrency())); smsParams.put("balance", savingsAccount.getWithdrawableBalance()); smsParams.put("officeId", client.getOffice().getId()); - smsParams.put("transactionDate", savingsAccountTransaction.getTransactionLocalDate().format(dateFormatter)); + smsParams.put("transactionDate", savingsAccountTransaction.getTransactionDate().format(dateFormatter)); smsParams.put("savingsTransactionId", savingsAccountTransaction.getId()); if (client.getStaff() != null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java index 0135ed70d32..64e8aeec326 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java @@ -30,7 +30,6 @@ import java.io.StringWriter; import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collection; @@ -54,12 +53,10 @@ 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.GeneralPlatformDomainRuleException; 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.ReportRepository; @@ -107,16 +104,16 @@ public class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP @Transactional @Override public CommandProcessingResult create(JsonCommand command) { - final AppUser currentUser = this.context.authenticatedUser(); this.smsCampaignValidator.validateCreate(command.json()); final Long runReportId = command.longValueOfParameterNamed(SmsCampaignValidator.runReportId); Report report = this.reportRepository.findById(runReportId).orElseThrow(() -> new ReportNotFoundException(runReportId)); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); SmsCampaign smsCampaign = SmsCampaign.instance(currentUser, report, command); - if (smsCampaign.getRecurrenceStartDate() != null - && smsCampaign.getRecurrenceStartDate().isBefore(DateUtils.getLocalDateTimeOfTenant())) { + LocalDateTime recurrenceStartDate = smsCampaign.getRecurrenceStartDate(); + if (recurrenceStartDate != null && DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) { throw new GeneralPlatformDomainRuleException("error.msg.campaign.recurrenceStartDate.in.the.past", - "Recurrence start date cannot be the past date.", smsCampaign.getRecurrenceStartDate()); + "Recurrence start date cannot be the past date.", recurrenceStartDate); } this.smsCampaignRepository.saveAndFlush(smsCampaign); @@ -380,17 +377,15 @@ public CommandProcessingResult activateSmsCampaign(Long campaignId, JsonCommand if (smsCampaign.isDirect()) { insertDirectCampaignIntoSmsOutboundTable(smsCampaign); } else if (smsCampaign.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 future calculate next trigger date if not use recurrence start date us + // next trigger date when activating LocalDateTime nextTriggerDate = null; - if (smsCampaign.getRecurrenceStartDateTime().isBefore(tenantDateTime())) { - nextTriggerDate = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getRecurrenceStartDate(), - DateUtils.getLocalDateTimeOfTenant()); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); + LocalDateTime recurrenceStartDate = smsCampaign.getRecurrenceStartDate(); + if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) { + nextTriggerDate = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), recurrenceStartDate, tenantDateTime); } else { - nextTriggerDate = smsCampaign.getRecurrenceStartDate(); + nextTriggerDate = recurrenceStartDate; } smsCampaign.setNextTriggerDate(nextTriggerDate); @@ -517,7 +512,6 @@ public CampaignPreviewData previewMessage(final JsonQuery query) { @Transactional @Override public CommandProcessingResult reactivateSmsCampaign(final Long campaignId, JsonCommand command) { - this.smsCampaignValidator.validateActivation(command.json()); final AppUser currentUser = this.context.authenticatedUser(); @@ -532,21 +526,16 @@ public CommandProcessingResult reactivateSmsCampaign(final Long campaignId, Json if (smsCampaign.isDirect()) { insertDirectCampaignIntoSmsOutboundTable(smsCampaign); } else if (smsCampaign.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 (smsCampaign.getRecurrenceStartDateTime().isBefore(tenantDateTime())) { - nextTriggerDate = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getRecurrenceStartDate(), - DateUtils.getLocalDateTimeOfTenant()); + LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant(); + LocalDateTime recurrenceStartDate = smsCampaign.getRecurrenceStartDate(); + if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) { + nextTriggerDate = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), recurrenceStartDate, tenantDateTime); } else { - nextTriggerDate = smsCampaign.getRecurrenceStartDate(); + nextTriggerDate = recurrenceStartDate; } - // to get time of tenant - final LocalDateTime getTime = smsCampaign.getRecurrenceStartDateTime(); - smsCampaign.setNextTriggerDate(nextTriggerDate); } this.smsCampaignRepository.saveAndFlush(smsCampaign); @@ -555,21 +544,7 @@ public CommandProcessingResult reactivateSmsCampaign(final Long campaignId, Json } private void handleDataIntegrityIssues(final JsonCommand command, final Throwable realCause) { - throw new PlatformDataIntegrityException("error.msg.sms.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/core/auditing/CustomAuditingHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandler.java index f7d755f5b6b..f8bfff14eb5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandler.java @@ -61,7 +61,7 @@ public CustomAuditingHandler(MappingContext, ? private DateTimeProvider fetchDateTimeProvider(Object bean) { if (bean instanceof AbstractAuditableWithUTCDateTimeCustom) { - return CustomDateTimeProvider.TENANT; + return CustomDateTimeProvider.UTC; } else { return CustomDateTimeProvider.INSTANCE; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProvider.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProvider.java index 839b18341aa..e2ce5d4354a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProvider.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProvider.java @@ -18,9 +18,6 @@ */ package org.apache.fineract.infrastructure.core.auditing; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.time.ZoneId; import java.time.temporal.TemporalAccessor; import java.util.Optional; import org.apache.fineract.infrastructure.core.service.DateUtils; @@ -29,7 +26,7 @@ public enum CustomDateTimeProvider implements DateTimeProvider { - INSTANCE, TENANT; + INSTANCE, UTC; /* * (non-Javadoc) @@ -42,10 +39,10 @@ public Optional getNow() { switch (this) { case INSTANCE -> { - return Optional.of(LocalDateTime.now(ZoneId.systemDefault())); + return Optional.of(DateUtils.getLocalDateTimeOfSystem()); } - case TENANT -> { - return Optional.of(OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant())); + case UTC -> { + return Optional.of(DateUtils.getAuditOffsetDateTime()); } } throw new UnsupportedOperationException(this + " is not supported!"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropAccountData.java index a22cf3dafda..8ce3d5309e5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropAccountData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropAccountData.java @@ -113,7 +113,7 @@ public static InteropAccountData build(SavingsAccount account) { return new InteropAccountData(account.getExternalId().getValue(), product.getId().toString(), product.getName(), product.getShortName(), account.getCurrency().getCode(), account.getAccountBalance(), account.getWithdrawableBalance(), - account.getStatus(), subStatus, account.getAccountType(), account.depositAccountType(), account.getActivationLocalDate(), + account.getStatus(), subStatus, account.getAccountType(), account.depositAccountType(), account.getActivationDate(), calcStatusUpdateOn(account), account.getWithdrawnOnDate(), account.retrieveLastTransactionDate(), ids, account.getClient().getId()); } @@ -125,8 +125,8 @@ private static LocalDate calcStatusUpdateOn(@NotNull SavingsAccount account) { if (account.getWithdrawnOnDate() != null) { return account.getWithdrawnOnDate(); } - if (account.getActivationLocalDate() != null) { - return account.getActivationLocalDate(); + if (account.getActivationDate() != null) { + return account.getActivationDate(); } if (account.getRejectedOnDate() != null) { return account.getRejectedOnDate(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionData.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionData.java index dd1106b6f91..64d45ef44f4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropTransactionData.java @@ -112,8 +112,8 @@ public static InteropTransactionData build(SavingsAccountTransaction transaction String currency = savingsAccount.getCurrency().getCode(); BigDecimal runningBalance = transaction.getRunningBalance(savingsAccount.getCurrency()).getAmount(); - LocalDate bookingDateTime = transaction.getTransactionLocalDate(); - LocalDate endOfBalanceLocalDate = transaction.getEndOfBalanceLocalDate(); + LocalDate bookingDateTime = transaction.getTransactionDate(); + LocalDate endOfBalanceLocalDate = transaction.getEndOfBalanceDate(); LocalDate valueDateTime = endOfBalanceLocalDate == null ? bookingDateTime : endOfBalanceLocalDate; StringBuilder sb = new StringBuilder(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/domain/InteropIdentifier.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/domain/InteropIdentifier.java index f6d48636323..1c50f0b3c82 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/domain/InteropIdentifier.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/domain/InteropIdentifier.java @@ -30,6 +30,7 @@ import java.time.LocalDateTime; import java.util.Objects; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; @Entity @@ -67,18 +68,17 @@ public class InteropIdentifier extends AbstractPersistableCustom { protected InteropIdentifier() {} public InteropIdentifier(@NotNull SavingsAccount account, @NotNull InteropIdentifierType type, @NotNull String value, String subType, - @NotNull String createdBy, @NotNull LocalDateTime createdOn) { + @NotNull String createdBy) { this.account = account; this.type = type; this.value = value; this.subType = subType; this.createdBy = createdBy; - this.createdOn = createdOn; + this.createdOn = DateUtils.getAuditLocalDateTime(); } - public InteropIdentifier(@NotNull SavingsAccount account, @NotNull InteropIdentifierType type, @NotNull String createdBy, - @NotNull LocalDateTime createdOn) { - this(account, type, null, null, createdBy, createdOn); + public InteropIdentifier(@NotNull SavingsAccount account, @NotNull InteropIdentifierType type, @NotNull String createdBy) { + this(account, type, null, null, createdBy); } public SavingsAccount getAccount() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java index e0746693705..828821c14a4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java @@ -243,7 +243,7 @@ public InteropTransactionsData getAccountTransactions(@NotNull String accountId, return true; } - java.time.LocalDateTime transactionDate = t.getTransactionLocalDate().atStartOfDay(ZoneId.systemDefault()).toLocalDateTime(); + java.time.LocalDateTime transactionDate = t.getTransactionDate().atStartOfDay(ZoneId.systemDefault()).toLocalDateTime(); return (transactionsTo == null || transactionsTo.compareTo(transactionDate) > 0) && (transactionsFrom == null || transactionsFrom.compareTo(transactionDate.withHour(23).withMinute(59).withSecond(59)) <= 0); }; @@ -276,16 +276,15 @@ public InteropIdentifierAccountResponseData getAccountByIdentifier(@NotNull Inte @Override public InteropIdentifierAccountResponseData registerAccountIdentifier(@NotNull InteropIdentifierType idType, @NotNull String idValue, String subIdOrType, @NotNull JsonCommand command) { - InteropIdentifierRequestData request = dataValidator.validateAndParseCreateIdentifier(idType, idValue, subIdOrType, command); // TODO: error handling SavingsAccount savingsAccount = validateAndGetSavingAccount(request.getAccountId()); try { - AppUser createdBy = getLoginUser(); + AppUser createdBy = securityContext.authenticatedUser(); InteropIdentifier identifier = new InteropIdentifier(savingsAccount, request.getIdType(), request.getIdValue(), - request.getSubIdOrType(), createdBy.getUsername(), DateUtils.getLocalDateTimeOfTenant()); + request.getSubIdOrType(), createdBy.getUsername()); identifierRepository.saveAndFlush(identifier); @@ -401,10 +400,9 @@ public InteropTransferResponseData prepareTransfer(@NotNull JsonCommand command) PaymentDetail paymentDetail = instance(findPaymentType(), savingsAccount.getExternalId().getValue(), null, getRoutingCode(), transferCode, null); SavingsAccountTransaction holdTransaction = SavingsAccountTransaction.holdAmount(savingsAccount, savingsAccount.office(), - paymentDetail, transactionDate, Money.of(savingsAccount.getCurrency(), total), DateUtils.getLocalDateTimeOfTenant(), - getLoginUser(), false); + paymentDetail, transactionDate, Money.of(savingsAccount.getCurrency(), total), false); MonetaryCurrency accountCurrency = savingsAccount.getCurrency().copy(); - holdTransaction.updateRunningBalance( + holdTransaction.setRunningBalance( Money.of(accountCurrency, savingsAccount.getWithdrawableBalance().subtract(holdTransaction.getAmount()))); holdTransaction.updateCumulativeBalanceAndDates(accountCurrency, transactionDate); @@ -454,8 +452,8 @@ public InteropTransferResponseData commitTransfer(@NotNull JsonCommand command) } if (holdTransaction.getReleaseIdOfHoldAmountTransaction() == null) { - SavingsAccountTransaction releaseTransaction = savingsAccountTransactionRepository.saveAndFlush( - releaseAmount(holdTransaction, transactionDate, DateUtils.getLocalDateTimeOfSystem(), getLoginUser())); + SavingsAccountTransaction releaseTransaction = savingsAccountTransactionRepository + .saveAndFlush(releaseAmount(holdTransaction, transactionDate)); holdTransaction.updateReleaseId(releaseTransaction.getId()); savingsAccount.releaseOnHoldAmount(holdTransaction.getAmount()); savingsAccount.addTransaction(releaseTransaction); @@ -493,11 +491,10 @@ public InteropTransferResponseData commitTransfer(@NotNull JsonCommand command) SavingsAccountTransaction holdTransaction = findTransaction(savingsAccount, request.getTransferCode(), AMOUNT_HOLD.getValue()); if (holdTransaction != null && holdTransaction.getReleaseIdOfHoldAmountTransaction() == null) { - SavingsAccountTransaction releaseTransaction = releaseAmount(holdTransaction, transactionDate, - DateUtils.getLocalDateTimeOfSystem(), getLoginUser()); + SavingsAccountTransaction releaseTransaction = releaseAmount(holdTransaction, transactionDate); MonetaryCurrency accountCurrency = savingsAccount.getCurrency().copy(); - releaseTransaction.updateRunningBalance( - Money.of(accountCurrency, savingsAccount.getWithdrawableBalance().add(holdTransaction.getAmount()))); + releaseTransaction + .setRunningBalance(Money.of(accountCurrency, savingsAccount.getWithdrawableBalance().add(holdTransaction.getAmount()))); releaseTransaction.updateCumulativeBalanceAndDates(accountCurrency, transactionDate); releaseTransaction = savingsAccountTransactionRepository.saveAndFlush(releaseTransaction); holdTransaction.updateReleaseId(releaseTransaction.getId()); @@ -652,10 +649,6 @@ public InteropIdentifier findIdentifier(@NotNull InteropIdentifierType idType, @ return identifierRepository.findOneByTypeAndValueAndSubType(idType, idValue, subIdOrType); } - private AppUser getLoginUser() { - return securityContext.getAuthenticatedUserIfPresent(); - } - /* * Guaranteed to throw an exception no matter what the data integrity issue is. */ diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java index 51e998ec765..a61ac96380f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java @@ -34,6 +34,7 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.calendar.CalendarConstants.CalendarSupportedParameters; import org.apache.fineract.portfolio.calendar.domain.Calendar; import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType; @@ -78,7 +79,7 @@ public CommandProcessingResult createCalendar(final JsonCommand command) { Group centerOrGroup = null; if (command.getGroupId() != null) { centerOrGroup = this.groupRepository.findOneWithNotFoundDetection(command.getGroupId()); - entityActivationDate = centerOrGroup.getActivationLocalDate(); + entityActivationDate = centerOrGroup.getActivationDate(); entityType = centerOrGroup.isCenter() ? CalendarEntityType.CENTERS : CalendarEntityType.GROUPS; entityId = command.getGroupId(); } else if (command.getLoanId() != null) { @@ -88,7 +89,7 @@ public CommandProcessingResult createCalendar(final JsonCommand command) { entityId = command.getLoanId(); } else if (command.getClientId() != null) { final Client client = this.clientRepository.findOneWithNotFoundDetection(command.getClientId()); - entityActivationDate = client.getActivationLocalDate(); + entityActivationDate = client.getActivationDate(); entityType = CalendarEntityType.CLIENTS; entityId = command.getClientId(); } @@ -98,7 +99,7 @@ public CommandProcessingResult createCalendar(final JsonCommand command) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("calendar"); - if (entityActivationDate == null || newCalendar.getStartDateLocalDate().isBefore(entityActivationDate)) { + if (entityActivationDate == null || DateUtils.isBefore(newCalendar.getStartDateLocalDate(), entityActivationDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); String dateAsString = ""; if (entityActivationDate != null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java index 22887192e9f..974aea51007 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java @@ -230,8 +230,7 @@ private void validateCharts(final DataValidatorBuilder baseDataValidator, final if (!existingChart.equals(this)) { if (this.chartFields.isOverlapping(existingChart.chartFields)) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.overlapping.from.and.end.dates", - existingChart.getFromDateAsLocalDate(), existingChart.getEndDateAsLocalDate(), this.getFromDateAsLocalDate(), - this.getEndDateAsLocalDate()); + existingChart.getFromDate(), existingChart.getEndDate(), this.getFromDate(), this.getEndDate()); } } } @@ -318,12 +317,12 @@ private boolean removeChartSlab(InterestRateChartSlab chartSlab) { return chartSlabs.remove(chartSlab); } - public LocalDate getFromDateAsLocalDate() { - return this.chartFields.getFromDateAsLocalDate(); + public LocalDate getFromDate() { + return this.chartFields.getFromDate(); } - public LocalDate getEndDateAsLocalDate() { - return this.chartFields.getEndDateAsLocalDate(); + public LocalDate getEndDate() { + return this.chartFields.getEndDate(); } private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java index ce1e68d6ed8..e1a78a96dc3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java @@ -88,7 +88,7 @@ public void update(JsonCommand command, final Map actualChanges, final String localeAsInput = command.locale(); final String dateFormat = command.dateFormat(); - if (command.isChangeInLocalDateParameterNamed(fromDateParamName, getFromDateAsLocalDate())) { + if (command.isChangeInLocalDateParameterNamed(fromDateParamName, getFromDate())) { final String newValueAsString = command.stringValueOfParameterNamed(fromDateParamName); actualChanges.put(fromDateParamName, newValueAsString); actualChanges.put(localeParamName, localeAsInput); @@ -96,7 +96,7 @@ public void update(JsonCommand command, final Map actualChanges, this.fromDate = command.localDateValueOfParameterNamed(fromDateParamName); } - if (command.isChangeInLocalDateParameterNamed(endDateParamName, getEndDateAsLocalDate())) { + if (command.isChangeInLocalDateParameterNamed(endDateParamName, getEndDate())) { final String newValueAsString = command.stringValueOfParameterNamed(endDateParamName); actualChanges.put(endDateParamName, newValueAsString); actualChanges.put(localeParamName, localeAsInput); @@ -116,31 +116,27 @@ public void update(JsonCommand command, final Map actualChanges, } public boolean isFromDateAfterToDate() { - return isFromDateAfter(getEndDateAsLocalDate()); + return isFromDateAfter(getEndDate()); } public boolean isFromDateAfter(LocalDate compare) { - final LocalDate fromDate = getFromDateAsLocalDate(); - if (fromDate != null && compare != null) { - return fromDate.isAfter(compare); - } - return false; + return compare != null && DateUtils.isAfter(getFromDate(), compare); } - public LocalDate getFromDateAsLocalDate() { + public LocalDate getFromDate() { return this.fromDate; } - public LocalDate getEndDateAsLocalDate() { + public LocalDate getEndDate() { return this.endDate; } public boolean isOverlapping(InterestRateChartFields that) { - final LocalDate thisFromDate = this.getFromDateAsLocalDate(); - LocalDate thisEndDate = this.getEndDateAsLocalDate(); + final LocalDate thisFromDate = this.getFromDate(); + LocalDate thisEndDate = this.getEndDate(); thisEndDate = thisEndDate == null ? DateUtils.getBusinessLocalDate() : thisEndDate; - final LocalDate thatFromDate = that.getFromDateAsLocalDate(); - LocalDate thatEndDate = that.getEndDateAsLocalDate(); + final LocalDate thatFromDate = that.getFromDate(); + LocalDate thatEndDate = that.getEndDate(); thatEndDate = thatEndDate == null ? DateUtils.getBusinessLocalDate() : thatEndDate; final LocalDateInterval thisInterval = LocalDateInterval.create(thisFromDate, thisEndDate); @@ -153,8 +149,8 @@ public boolean isOverlapping(InterestRateChartFields that) { } public boolean isApplicableChartFor(final LocalDate target) { - final LocalDate endDate = this.endDate == null ? DateUtils.getBusinessLocalDate() : this.getEndDateAsLocalDate(); - final LocalDateInterval interval = LocalDateInterval.create(getFromDateAsLocalDate(), endDate); + final LocalDate endDate = this.endDate == null ? DateUtils.getBusinessLocalDate() : this.getEndDate(); + final LocalDateInterval interval = LocalDateInterval.create(getFromDate(), endDate); return interval.contains(target); } 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 4b9f06465c4..21ee7b02bcd 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 @@ private void holdGuarantorFunds(final Loan loan) { if (loan.isApproved() && !loan.isDisbursed()) { final List transactions = new ArrayList<>(); for (final SavingsAccountTransaction transaction : savingsAccount.getTransactions()) { - if (!transaction.getTransactionLocalDate().isAfter(loan.getApprovedOnDate())) { + if (!transaction.getTransactionDate().isAfter(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 770652be8b4..1c055efd4e9 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,12 +187,12 @@ private CommandProcessingResult createGuarantor(final Loan loan, final JsonComma private void validateGuarantorSavingsAccountActivationDateWithLoanSubmittedOnDate(final Loan loan, final SavingsAccount savingsAccount) { - if (loan.getSubmittedOnDate().isBefore(savingsAccount.getActivationLocalDate())) { + if (loan.getSubmittedOnDate().isBefore(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.getActivationLocalDate() + "Guarantor saving account activation date [" + savingsAccount.getActivationDate() + "] is on or before the loan submitted on date [" + loan.getSubmittedOnDate() + "]", - savingsAccount.getActivationLocalDate(), loan.getSubmittedOnDate()); + savingsAccount.getActivationDate(), loan.getSubmittedOnDate()); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java index 0b3bae56668..46adf4221e5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java @@ -23,6 +23,7 @@ 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; import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartData; import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabData; @@ -159,12 +160,11 @@ public void addChartSlab(final DepositAccountInterestRateChartSlabData chartSlab if (this.chartSlabs == null) { this.chartSlabs = new ArrayList<>(); } - this.chartSlabs.add(chartSlab); } 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/savings/data/SavingsAccountTransactionDTO.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDTO.java index 37b38a896cf..de3a62022e0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDTO.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDTO.java @@ -20,10 +20,8 @@ import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail; -import org.apache.fineract.useradministration.domain.AppUser; public class SavingsAccountTransactionDTO { @@ -31,24 +29,9 @@ public class SavingsAccountTransactionDTO { private final LocalDate transactionDate; private final BigDecimal transactionAmount; private final PaymentDetail paymentDetail; - private final LocalDateTime createdDate; private final Long savingsAccountId; - private final AppUser appUser; private final Integer depositAccountType; - public SavingsAccountTransactionDTO(final DateTimeFormatter formatter, final LocalDate transactionDate, - final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final LocalDateTime createdDate, final AppUser appUser, - final Integer depositAccountType) { - this.formatter = formatter; - this.transactionDate = transactionDate; - this.transactionAmount = transactionAmount; - this.paymentDetail = paymentDetail; - this.createdDate = createdDate; - this.savingsAccountId = null; - this.appUser = appUser; - this.depositAccountType = depositAccountType; - } - /** * This constructor is used for bulk deposit transactions * @@ -56,19 +39,15 @@ public SavingsAccountTransactionDTO(final DateTimeFormatter formatter, final Loc * @param transactionDate * @param transactionAmount * @param paymentDetail - * @param createdDate * @param savingsAccountId */ public SavingsAccountTransactionDTO(DateTimeFormatter formatter, LocalDate transactionDate, BigDecimal transactionAmount, - PaymentDetail paymentDetail, LocalDateTime createdDate, Long savingsAccountId, AppUser appUser, - final Integer depositAccountType) { + PaymentDetail paymentDetail, Long savingsAccountId, final Integer depositAccountType) { this.formatter = formatter; this.transactionDate = transactionDate; this.transactionAmount = transactionAmount; this.paymentDetail = paymentDetail; - this.createdDate = createdDate; this.savingsAccountId = savingsAccountId; - this.appUser = appUser; this.depositAccountType = depositAccountType; } @@ -88,18 +67,10 @@ public PaymentDetail getPaymentDetail() { return this.paymentDetail; } - public LocalDateTime getCreatedDate() { - return this.createdDate; - } - public Long getSavingsAccountId() { return this.savingsAccountId; } - public AppUser getAppUser() { - return this.appUser; - } - public Integer getAccountType() { return this.depositAccountType; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java index 802e4c41d5b..fd950926fea 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java @@ -37,7 +37,6 @@ import java.lang.reflect.Type; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -83,7 +82,6 @@ public SavingsAccountTransactionDataValidator(final FromJsonHelper fromApiJsonHe } public void validateTransactionWithPivotDate(final LocalDate transactionDate, final SavingsAccount savingsAccount) { - final boolean backdatedTxnsAllowedTill = this.configurationDomainService.retrievePivotDateConfig(); final boolean isRelaxingDaysConfigOn = this.configurationDomainService.isRelaxingDaysConfigForPivotDateEnabled(); @@ -94,14 +92,13 @@ public void validateTransactionWithPivotDate(final LocalDate transactionDate, fi if (isRelaxingDaysConfigOn) { pivotDate = pivotDate.minusDays(this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate()); } - if (pivotDate.isAfter(transactionDate)) { + if (DateUtils.isAfter(pivotDate, transactionDate)) { throw new TransactionBeforePivotDateNotAllowed(transactionDate, pivotDate); } } } public void validate(final JsonCommand command) { - final String json = command.json(); if (StringUtils.isBlank(json)) { @@ -296,7 +293,7 @@ public void validateHoldAndAssembleForm(final String json, final SavingsAccount } // compare two dates now - if (lastTransactionDate != null && transactionDate.isBefore(lastTransactionDate)) { + if (DateUtils.isBefore(transactionDate, lastTransactionDate)) { baseDataValidator.parameter(SavingsApiConstants.dateParamName).value(lastTransactionDate).failWithCode( "validation.msg.date.can.not.be.before.last.transaction.date", "Amount can be put on hold only after last transaction"); } @@ -304,8 +301,7 @@ public void validateHoldAndAssembleForm(final String json, final SavingsAccount throwExceptionIfValidationWarningsExist(dataValidationErrors); } - public SavingsAccountTransaction validateReleaseAmountAndAssembleForm(final SavingsAccountTransaction holdTransaction, - final AppUser createdUser) { + public SavingsAccountTransaction validateReleaseAmountAndAssembleForm(final SavingsAccountTransaction holdTransaction) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(SAVINGS_ACCOUNT_RESOURCE_NAME); @@ -326,10 +322,8 @@ public SavingsAccountTransaction validateReleaseAmountAndAssembleForm(final Savi } throwExceptionIfValidationWarningsExist(dataValidationErrors); - LocalDateTime createdDate = DateUtils.getLocalDateTimeOfSystem(); LocalDate transactionDate = DateUtils.getBusinessLocalDate(); - SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction, transactionDate, createdDate, - createdUser); + SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction, transactionDate); return transaction; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java index 317c6b03b07..af3b000cfa8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java @@ -69,7 +69,6 @@ import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; 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.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.organisation.staff.domain.Staff; @@ -358,7 +357,7 @@ public SavingsAccount assembleFrom(final JsonCommand command, final AppUser subm if (account != null) { account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper); - account.validateNewApplicationState(DateUtils.getBusinessLocalDate(), depositAccountType.resourceName()); + account.validateNewApplicationState(depositAccountType.resourceName()); } return account; @@ -448,7 +447,6 @@ public DepositAccountRecurringDetail assembleAccountRecurringDetail(final JsonCo public Collection assembleBulkMandatorySavingsAccountTransactionDTOs(final JsonCommand command, final PaymentDetail paymentDetail) { - AppUser user = getAppUserIfPresent(); final String json = command.json(); if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); @@ -478,7 +476,7 @@ public Collection assembleBulkMandatorySavingsAcco detail = this.paymentDetailAssembler.fetchPaymentDetail(savingsTransactionElement); } final SavingsAccountTransactionDTO savingsAccountTransactionDTO = new SavingsAccountTransactionDTO(formatter, - transactionDate, dueAmount, detail, DateUtils.getLocalDateTimeOfSystem(), savingsId, user, depositAccountType); + transactionDate, dueAmount, detail, savingsId, depositAccountType); savingsAccountTransactions.add(savingsAccountTransactionDTO); } } @@ -486,13 +484,4 @@ public Collection assembleBulkMandatorySavingsAcco return savingsAccountTransactions; } - - private AppUser getAppUserIfPresent() { - AppUser user = null; - if (this.context != null) { - user = this.context.getAuthenticatedUserIfPresent(); - } - return user; - } - } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java index 34fe6d04ff1..3b29b900c14 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java @@ -42,19 +42,18 @@ SavingsAccountTransaction handleSavingDeposit(SavingsAccount account, DateTimeFo BigDecimal transactionAmount, PaymentDetail paymentDetail, boolean isRegularTransaction); Long handleFDAccountClosure(FixedDepositAccount account, PaymentDetail paymentDetail, AppUser user, JsonCommand command, - LocalDate tenantsTodayDate, Map changes); + Map changes); @Transactional - Long handleFDAccountMaturityClosure(FixedDepositAccount account, PaymentDetail paymentDetail, AppUser user, LocalDate tenantsTodayDate, - DateTimeFormatter fmt, LocalDate closedDate, Integer onAccountClosureId, Long toSavingsId, String transferDescription, - Map changes); + Long handleFDAccountMaturityClosure(FixedDepositAccount account, PaymentDetail paymentDetail, AppUser user, DateTimeFormatter fmt, + LocalDate closedDate, Integer onAccountClosureId, Long toSavingsId, String transferDescription, Map changes); Long handleRDAccountClosure(RecurringDepositAccount account, PaymentDetail paymentDetail, AppUser user, JsonCommand command, - LocalDate tenantsTodayDate, Map changes); + Map changes); Long handleFDAccountPreMatureClosure(FixedDepositAccount account, PaymentDetail paymentDetail, AppUser user, JsonCommand command, - LocalDate tenantsTodayDate, Map changes); + Map changes); Long handleRDAccountPreMatureClosure(RecurringDepositAccount account, PaymentDetail paymentDetail, AppUser user, JsonCommand command, - LocalDate tenantsTodayDate, Map changes); + Map changes); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java index 16e01e30c5a..52290bc4c42 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java @@ -40,8 +40,6 @@ import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException; import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; -import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; import org.apache.fineract.portfolio.account.PortfolioAccountType; import org.apache.fineract.portfolio.account.data.AccountTransferDTO; import org.apache.fineract.portfolio.account.domain.AccountTransferType; @@ -69,9 +67,7 @@ @Service public class DepositAccountDomainServiceJpa implements DepositAccountDomainService { - private final PlatformSecurityContext context; private final SavingsAccountRepositoryWrapper savingsAccountRepository; - private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper; private final JournalEntryWritePlatformService journalEntryWritePlatformService; private final AccountNumberGenerator accountNumberGenerator; private final DepositAccountAssembler depositAccountAssembler; @@ -82,18 +78,14 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi private final CalendarInstanceRepository calendarInstanceRepository; @Autowired - public DepositAccountDomainServiceJpa(final PlatformSecurityContext context, - final SavingsAccountRepositoryWrapper savingsAccountRepository, - final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper, + public DepositAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savingsAccountRepository, final JournalEntryWritePlatformService journalEntryWritePlatformService, final AccountNumberGenerator accountNumberGenerator, final DepositAccountAssembler depositAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService, final AccountTransfersWritePlatformService accountTransfersWritePlatformService, final ConfigurationDomainService configurationDomainService, final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final CalendarInstanceRepository calendarInstanceRepository) { - this.context = context; this.savingsAccountRepository = savingsAccountRepository; - this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper; this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.accountNumberGenerator = accountNumberGenerator; this.depositAccountAssembler = depositAccountAssembler; @@ -135,7 +127,6 @@ public SavingsAccountTransaction handleFDDeposit(final FixedDepositAccount accou public SavingsAccountTransaction handleRDDeposit(final RecurringDepositAccount account, final DateTimeFormatter fmt, final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final boolean isRegularTransaction) { - AppUser user = getAppUserIfPresent(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth(); @@ -151,7 +142,7 @@ public SavingsAccountTransaction handleRDDeposit(final RecurringDepositAccount a final boolean isAnyActivationChargesDue = isAnyActivationChargesDue(account); if (isAnyActivationChargesDue) { updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - account.processAccountUponActivation(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, user); + account.processAccountUponActivation(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth); this.savingsAccountRepository.saveAndFlush(account); } account.handleScheduleInstallments(deposit); @@ -193,8 +184,7 @@ private boolean isAnyActivationChargesDue(final RecurringDepositAccount account) @Transactional @Override public Long handleFDAccountClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user, - final JsonCommand command, final LocalDate tenantsTodayDate, final Map changes) { - + final JsonCommand command, final Map changes) { final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth(); @@ -204,9 +194,7 @@ public Long handleFDAccountClosure(final FixedDepositAccount account, final Paym final boolean isPreMatureClosure = false; final Set existingTransactionIds = new HashSet<>(); final Set existingReversedTransactionIds = new HashSet<>(); - /*** - * Update account transactionIds for post journal entries. - */ + // Update account transactionIds for post journal entries. updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); /* * final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, @@ -254,7 +242,7 @@ public Long handleFDAccountClosure(final FixedDepositAccount account, final Paym savingsTransactionId = withdrawal.getId(); } - account.close(user, command, tenantsTodayDate, changes); + account.close(user, command, changes); this.savingsAccountRepository.save(account); return savingsTransactionId; @@ -263,8 +251,8 @@ public Long handleFDAccountClosure(final FixedDepositAccount account, final Paym @Transactional @Override public Long handleFDAccountMaturityClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user, - final LocalDate tenantsTodayDate, final DateTimeFormatter fmt, final LocalDate closedDate, final Integer onAccountClosureId, - final Long toSavingsId, final String transferDescription, Map changes) { + final DateTimeFormatter fmt, final LocalDate closedDate, final Integer onAccountClosureId, final Long toSavingsId, + final String transferDescription, Map changes) { final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -329,7 +317,7 @@ public Long handleFDAccountMaturityClosure(final FixedDepositAccount account, fi } // if(!processMaturityInstructionOnly) - // account.close(user, command, tenantsTodayDate, changes); + // account.close(user, command, changes); this.savingsAccountRepository.save(account); @@ -341,7 +329,7 @@ public Long handleFDAccountMaturityClosure(final FixedDepositAccount account, fi @Transactional @Override public Long handleRDAccountClosure(final RecurringDepositAccount account, final PaymentDetail paymentDetail, final AppUser user, - final JsonCommand command, final LocalDate tenantsTodayDate, final Map changes) { + final JsonCommand command, final Map changes) { final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -352,9 +340,7 @@ public Long handleRDAccountClosure(final RecurringDepositAccount account, final final boolean isPreMatureClosure = false; final Set existingTransactionIds = new HashSet<>(); final Set existingReversedTransactionIds = new HashSet<>(); - /*** - * Update account transactionIds for post journal entries. - */ + // Update account transactionIds for post journal entries. updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); final MathContext mc = MathContext.DECIMAL64; @@ -383,7 +369,7 @@ public Long handleRDAccountClosure(final RecurringDepositAccount account, final Integer frequency = CalendarUtils.getInterval(calendar.getRecurrence()); frequency = frequency == -1 ? 1 : frequency; reinvestedDeposit.generateSchedule(frequencyType, frequency, calendar); - reinvestedDeposit.processAccountUponActivation(fmt, user, postReversals); + reinvestedDeposit.processAccountUponActivation(fmt, postReversals); reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth); this.savingsAccountRepository.save(reinvestedDeposit); @@ -411,7 +397,7 @@ public Long handleRDAccountClosure(final RecurringDepositAccount account, final savingsTransactionId = withdrawal.getId(); } - account.close(user, command, tenantsTodayDate, changes); + account.close(user, command, changes); this.savingsAccountRepository.save(account); @@ -456,7 +442,7 @@ private void autoGenerateAccountNumber(final SavingsAccount account) { @Transactional @Override public Long handleFDAccountPreMatureClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user, - final JsonCommand command, final LocalDate tenantsTodayDate, final Map changes) { + final JsonCommand command, final Map changes) { final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -467,9 +453,7 @@ public Long handleFDAccountPreMatureClosure(final FixedDepositAccount account, f final boolean isPreMatureClosure = true; final Set existingTransactionIds = new HashSet<>(); final Set existingReversedTransactionIds = new HashSet<>(); - /*** - * Update account transactionIds for post journal entries. - */ + // Update account transactionIds for post journal entries. updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); @@ -502,7 +486,7 @@ public Long handleFDAccountPreMatureClosure(final FixedDepositAccount account, f savingsTransactionId = withdrawal.getId(); } - account.prematureClosure(user, command, tenantsTodayDate, changes); + account.prematureClosure(user, command, changes); this.savingsAccountRepository.save(account); @@ -513,7 +497,7 @@ public Long handleFDAccountPreMatureClosure(final FixedDepositAccount account, f @Transactional @Override public Long handleRDAccountPreMatureClosure(final RecurringDepositAccount account, final PaymentDetail paymentDetail, - final AppUser user, final JsonCommand command, final LocalDate tenantsTodayDate, final Map changes) { + final AppUser user, final JsonCommand command, final Map changes) { final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -558,7 +542,7 @@ public Long handleRDAccountPreMatureClosure(final RecurringDepositAccount accoun savingsTransactionId = withdrawal.getId(); } - account.prematureClosure(user, command, tenantsTodayDate, changes); + account.prematureClosure(user, command, changes); this.savingsAccountRepository.save(account); postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer); return savingsTransactionId; @@ -592,12 +576,4 @@ private void updateAlreadyPostedTransactions(final Set existingTransaction } } } - - private AppUser getAppUserIfPresent() { - AppUser user = null; - if (this.context != null) { - user = this.context.getAuthenticatedUserIfPresent(); - } - return user; - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java index 8f3d40b7ad5..36a2358aaf2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java @@ -103,12 +103,12 @@ public DepositAccountInterestRateChartSlabs findChartSlab(Long chartSlabId) { return null; } - public LocalDate getFromDateAsLocalDate() { - return this.chartFields.getFromDateAsLocalDate(); + public LocalDate getFromDate() { + return this.chartFields.getFromDate(); } - public LocalDate getEndDateAsLocalDate() { - return this.chartFields.getEndDateAsLocalDate(); + public LocalDate getEndDate() { + return this.chartFields.getEndDate(); } public Long savingsAccountId() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountOnHoldTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountOnHoldTransaction.java index 029c2500c93..78a5f2f8062 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountOnHoldTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountOnHoldTransaction.java @@ -18,6 +18,8 @@ */ package org.apache.fineract.portfolio.savings.domain; +import static org.apache.fineract.infrastructure.core.service.DateUtils.getSystemZoneId; + import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -28,8 +30,9 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; -import org.apache.fineract.infrastructure.core.service.DateUtils; +import java.time.OffsetDateTime; +import java.util.Optional; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.guarantor.domain.GuarantorFundingTransaction; @@ -37,7 +40,7 @@ @Entity @Table(name = "m_deposit_account_on_hold_transaction") -public class DepositAccountOnHoldTransaction extends AbstractPersistableCustom { +public class DepositAccountOnHoldTransaction extends AbstractAuditableWithUTCDateTimeCustom { @ManyToOne @JoinColumn(name = "savings_account_id", nullable = true) @@ -55,8 +58,9 @@ public class DepositAccountOnHoldTransaction extends AbstractPersistableCustom { @Column(name = "is_reversed", nullable = false) private boolean reversed; - @Column(name = "created_date", nullable = false) - private LocalDateTime createdDate; + @Deprecated + @Column(name = "created_date", nullable = true) + private LocalDateTime createdDateToRemove; @OneToOne(cascade = CascadeType.ALL, mappedBy = "depositAccountOnHoldTransaction", optional = true, orphanRemoval = true) private GuarantorFundingTransaction guarantorFundingTransaction; @@ -69,7 +73,7 @@ private DepositAccountOnHoldTransaction(final SavingsAccount savingsAccount, fin this.amount = amount; this.transactionType = transactionType.getValue(); this.transactionDate = transactionDate; - this.createdDate = DateUtils.getLocalDateTimeOfSystem(); + this.createdDateToRemove = null; // #audit backward compatibility deprecated this.reversed = reversed; } @@ -87,14 +91,30 @@ public static DepositAccountOnHoldTransaction release(final SavingsAccount savin reversed); } + public SavingsAccount getSavingsAccount() { + return savingsAccount; + } + public BigDecimal getAmount() { return this.amount; } - public Money getAmountMoney(final MonetaryCurrency currency) { + public Money getAmount(final MonetaryCurrency currency) { return Money.of(currency, this.amount); } + public DepositAccountOnHoldTransactionType getTransactionType() { + return DepositAccountOnHoldTransactionType.fromInt(this.transactionType); + } + + public LocalDate getTransactionDate() { + return this.transactionDate; + } + + public MonetaryCurrency getCurrency() { + return getSavingsAccount().getCurrency(); + } + public void reverseTransaction() { this.reversed = true; if (this.getTransactionType().isHold()) { @@ -104,12 +124,10 @@ public void reverseTransaction() { } } - public DepositAccountOnHoldTransactionType getTransactionType() { - return DepositAccountOnHoldTransactionType.fromInt(this.transactionType); - } - - public LocalDate getTransactionDate() { - return this.transactionDate; + @Override + public Optional getCreatedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getCreatedDate() + .orElse(createdDateToRemove == null ? null : createdDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); } - } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java index 1bc13d84289..64553b3b406 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java @@ -224,7 +224,7 @@ public void updateDepositAmount(final BigDecimal depositAmount) { this.depositAmount = depositAmount; } - public LocalDate getMaturityLocalDate() { + public LocalDate getMaturityDate() { return this.maturityDate; } @@ -247,7 +247,7 @@ public Integer getActualDepositPeriod(final LocalDate interestPostingUpToDate, f } Integer actualDepositPeriod = this.depositPeriod; - if (depositFromDate == null || getMaturityLocalDate() == null || interestPostingUpToDate.isEqual(getMaturityLocalDate())) { + if (depositFromDate == null || getMaturityDate() == null || DateUtils.isEqual(interestPostingUpToDate, getMaturityDate())) { return actualDepositPeriod; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java index b07cd1569f3..2855bc1e566 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java @@ -197,18 +197,8 @@ public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext String refNo = null; final Money transactionAmountMoney = Money.of(getCurrency(), this.accountTermAndPreClosure.depositAmount()); final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(null, office(), null, - this.accountSubmittedOrActivationDate(), transactionAmountMoney, DateUtils.getLocalDateTimeOfSystem(), null, refNo); // TODO: - // verify - // if - // it - // is - // ok - // to - // pass - // null - // for - // AppUser - transaction.updateRunningBalance(transactionAmountMoney); + this.accountSubmittedOrActivationDate(), transactionAmountMoney, refNo); + transaction.setRunningBalance(transactionAmountMoney); transaction.updateCumulativeBalanceAndDates(this.getCurrency(), interestCalculatedUpto()); allTransactions.add(transaction); updateMaturityDateAndAmount(mc, allTransactions, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd, @@ -260,8 +250,7 @@ public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrent } } - final LocalDate todayDate = DateUtils.getBusinessLocalDate(); - if (!this.maturityDate().isAfter(todayDate)) { + if (!DateUtils.isDateInTheFuture(maturityDate())) { // update account status this.status = SavingsAccountStatusType.MATURED.getValue(); postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth); @@ -338,14 +327,12 @@ private List calculateInterestPayable(final MathContext mc, final } this.summary.updateFromInterestPeriodSummaries(this.currency, allPostingPeriods); - this.savingsHelper.calculateInterestForAllPostingPeriods(this.currency, allPostingPeriods, this.getLockedInUntilLocalDate(), + this.savingsHelper.calculateInterestForAllPostingPeriods(this.currency, allPostingPeriods, getLockedInUntilDate(), isTransferInterestToOtherAccount()); return allPostingPeriods; } - public void prematureClosure(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, - final Map actualChanges) { - + public void prematureClosure(final AppUser currentUser, final JsonCommand command, final Map actualChanges) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME + DepositsApiConstants.preMatureCloseAction); @@ -362,14 +349,13 @@ public void prematureClosure(final AppUser currentUser, final JsonCommand comman final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); - if (closedDate.isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(closedDate, getActivationDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (isAccountLocked(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.lockin.period"); @@ -377,16 +363,14 @@ public void prematureClosure(final AppUser currentUser, final JsonCommand comman throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (closedDate.isAfter(maturityDate())) { + if (maturityDate() != null && DateUtils.isAfter(closedDate, maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.before.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (closedDate.isAfter(tenantsTodayDate)) { + if (DateUtils.isAfterBusinessDate(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { @@ -437,9 +421,7 @@ public Money activateWithBalance() { return Money.of(this.currency, this.accountTermAndPreClosure.depositAmount()); } - public void close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, - final Map actualChanges) { - + public void close(final AppUser currentUser, final JsonCommand command, final Map actualChanges) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.closeAction); @@ -456,21 +438,21 @@ public void close(final AppUser currentUser, final JsonCommand command, final Lo final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); - if (closedDate.isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(closedDate, getActivationDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (closedDate.isBefore(maturityDate())) { + if (DateUtils.isBefore(closedDate, maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.account.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (closedDate.isAfter(tenantsTodayDate)) { + if (DateUtils.isAfterBusinessDate(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { @@ -548,7 +530,8 @@ public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrent LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); - interestPostingTransactionDate = interestPostingTransactionDate.isAfter(interestPostingUpToDate) ? interestPostingUpToDate + interestPostingTransactionDate = DateUtils.isAfter(interestPostingTransactionDate, interestPostingUpToDate) + ? interestPostingUpToDate : interestPostingTransactionDate; final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); @@ -669,14 +652,14 @@ public List calculateInterestUsing(final MathContext mc, final Lo private LocalDate interestPostingUpToDate(final LocalDate interestPostingDate) { LocalDate interestPostingUpToDate = interestPostingDate; final LocalDate uptoMaturityDate = interestCalculatedUpto(); - if (uptoMaturityDate != null && uptoMaturityDate.isBefore(interestPostingDate)) { + if (uptoMaturityDate != null && DateUtils.isBefore(uptoMaturityDate, interestPostingDate)) { interestPostingUpToDate = uptoMaturityDate; } return interestPostingUpToDate; } public LocalDate maturityDate() { - return this.accountTermAndPreClosure.getMaturityLocalDate(); + return this.accountTermAndPreClosure.getMaturityDate(); } public BigDecimal maturityAmount() { @@ -695,8 +678,8 @@ private Money totalInterestPosted() { } @Override - public Map activate(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { - final Map actualChanges = super.activate(currentUser, command, tenantsTodayDate); + public Map activate(final AppUser currentUser, final JsonCommand command) { + final Map actualChanges = super.activate(currentUser, command); // if (isAccountLocked(calculateMaturityDate())) { // final List dataValidationErrors = new @@ -770,8 +753,8 @@ private void validateDomainRules(final DataValidatorBuilder baseDataValidator) { } if (this.chart != null) { - final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate(); - LocalDate chartEndDate = this.chart.getEndDateAsLocalDate(); + final LocalDate chartFromDate = this.chart.getFromDate(); + LocalDate chartEndDate = this.chart.getEndDate(); chartEndDate = chartEndDate == null ? DateUtils.getBusinessLocalDate() : chartEndDate; final LocalDateInterval chartInterval = LocalDateInterval.create(chartFromDate, chartEndDate); @@ -783,7 +766,7 @@ private void validateDomainRules(final DataValidatorBuilder baseDataValidator) { BigDecimal applicableInterestRate = this.chart.getApplicableInterestRate(depositAmount, depositStartDate(), calculateMaturityDate(), this.client); - if (applicableInterestRate.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE : Boolean.FALSE) { + if (applicableInterestRate.compareTo(BigDecimal.ZERO) == 0) { baseDataValidator.reset() .failWithCodeNoParameterAddedToErrorCode("no.applicable.interest.rate.is.found.based.on.amount.and.deposit.period"); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java index f87d6140a9b..216770856c3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java @@ -258,8 +258,8 @@ public void validateChart(final DataValidatorBuilder baseDataValidator, final In if (!existingChart.equals(comparingChart)) { if (existingChart.chartFields().isOverlapping(comparingChart.chartFields())) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.overlapping.from.and.end.dates", - existingChart.getFromDateAsLocalDate(), existingChart.getEndDateAsLocalDate(), - comparingChart.getFromDateAsLocalDate(), comparingChart.getEndDateAsLocalDate()); + existingChart.getFromDate(), existingChart.getEndDate(), comparingChart.getFromDate(), + comparingChart.getEndDate()); } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java index f21fce256e5..5eea23621b2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java @@ -286,7 +286,7 @@ public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrent } final LocalDate todayDate = DateUtils.getBusinessLocalDate(); - if (!this.maturityDate().isAfter(todayDate)) { + if (!DateUtils.isAfter(this.maturityDate(), todayDate)) { // update account status this.status = SavingsAccountStatusType.MATURED.getValue(); postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, todayDate, postReversals); @@ -368,7 +368,7 @@ private List calculateInterestPayable(final MathContext mc, final allPostingPeriods.add(postingPeriod); } - this.savingsHelper.calculateInterestForAllPostingPeriods(this.currency, allPostingPeriods, this.getLockedInUntilLocalDate(), + this.savingsHelper.calculateInterestForAllPostingPeriods(this.currency, allPostingPeriods, this.getLockedInUntilDate(), isTransferInterestToOtherAccount()); // this.summary.updateFromInterestPeriodSummaries(this.currency, // allPostingPeriods); @@ -381,8 +381,8 @@ private List getTransactions(final LocalDate depositE allTransactions.addAll(retreiveOrderedNonInterestPostingTransactions()); LocalDate latestTransactionDate = null; for (final SavingsAccountTransaction installment : allTransactions) { - if (latestTransactionDate == null || latestTransactionDate.isBefore(installment.getTransactionLocalDate())) { - latestTransactionDate = installment.getTransactionLocalDate(); + if (latestTransactionDate == null || DateUtils.isBefore(latestTransactionDate, installment.getTransactionDate())) { + latestTransactionDate = installment.getTransactionDate(); } } String refNo = null; @@ -390,11 +390,11 @@ private List getTransactions(final LocalDate depositE for (RecurringDepositScheduleInstallment installment : depositScheduleInstallments()) { if (installment.isPrincipalNotCompleted(getCurrency())) { LocalDate dueDate = installment.dueDate(); - if (latestTransactionDate != null && dueDate.isBefore(latestTransactionDate)) { + if (DateUtils.isBefore(dueDate, latestTransactionDate)) { dueDate = latestTransactionDate; } final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(null, office(), null, dueDate, - installment.getDepositAmountOutstanding(getCurrency()), DateUtils.getLocalDateTimeOfSystem(), null, refNo); + installment.getDepositAmountOutstanding(getCurrency()), refNo); allTransactions.add(transaction); } } @@ -414,7 +414,7 @@ private List getTransactions(final LocalDate depositE } runningBalance = runningBalance.plus(transactionAmount); - transaction.updateRunningBalance(runningBalance); + transaction.setRunningBalance(runningBalance); } } // loop over transactions in reverse @@ -423,7 +423,7 @@ private List getTransactions(final LocalDate depositE final SavingsAccountTransaction transaction = allTransactions.get(i); if (transaction.isNotReversed() && !transaction.isInterestPostingAndNotReversed()) { transaction.updateCumulativeBalanceAndDates(this.currency, endOfBalanceDate); - endOfBalanceDate = transaction.transactionLocalDate().minusDays(1); + endOfBalanceDate = transaction.getTransactionDate().minusDays(1); } } return allTransactions; @@ -437,9 +437,7 @@ public LocalDate depositStartDate() { return depositStartDate; } - public void prematureClosure(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, - final Map actualChanges) { - + public void prematureClosure(final AppUser currentUser, final JsonCommand command, final Map actualChanges) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME + DepositsApiConstants.preMatureCloseAction); @@ -456,14 +454,13 @@ public void prematureClosure(final AppUser currentUser, final JsonCommand comman final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); - if (closedDate.isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(closedDate, getActivationDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (isAccountLocked(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.lockin.period"); @@ -471,16 +468,14 @@ public void prematureClosure(final AppUser currentUser, final JsonCommand comman throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (closedDate.isAfter(maturityDate())) { + if (maturityDate() != null && DateUtils.isAfter(closedDate, maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.before.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (closedDate.isAfter(tenantsTodayDate)) { + if (DateUtils.isAfterBusinessDate(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { @@ -541,14 +536,14 @@ public Money activateWithBalance() { return Money.of(this.currency, this.minRequiredOpeningBalance); } - protected void processAccountUponActivation(final DateTimeFormatter fmt, final AppUser user, final boolean postReversals) { + protected void processAccountUponActivation(final DateTimeFormatter fmt, final boolean postReversals) { final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance); final boolean backdatedTxnsAllowedTill = false; String refNo = null; final Long relaxingDaysConfigForPivotDate = this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate(); if (minRequiredOpeningBalance.isGreaterThanZero()) { - final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(), - minRequiredOpeningBalance.getAmount(), null, DateUtils.getLocalDateTimeOfSystem(), user, accountType); + final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationDate(), + minRequiredOpeningBalance.getAmount(), null, null, accountType); deposit(transactionDTO, backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate, refNo); // update existing transactions so derived balance fields are @@ -557,9 +552,7 @@ protected void processAccountUponActivation(final DateTimeFormatter fmt, final A } } - public void close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, - final Map actualChanges) { - + public void close(final AppUser currentUser, final JsonCommand command, final Map actualChanges) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.closeAction); @@ -576,21 +569,21 @@ public void close(final AppUser currentUser, final JsonCommand command, final Lo final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); - if (closedDate.isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(closedDate, getActivationDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (maturityDate() != null && closedDate.isBefore(maturityDate())) { + if (maturityDate() != null && DateUtils.isBefore(closedDate, maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.account.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (closedDate.isAfter(tenantsTodayDate)) { + if (DateUtils.isAfterBusinessDate(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { @@ -659,7 +652,8 @@ public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrent for (final PostingPeriod interestPostingPeriod : postingPeriods) { LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); - interestPostingTransactionDate = interestPostingTransactionDate.isAfter(interestPostingUpToDate) ? interestPostingUpToDate + interestPostingTransactionDate = DateUtils.isAfter(interestPostingTransactionDate, interestPostingUpToDate) + ? interestPostingUpToDate : interestPostingTransactionDate; final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); @@ -777,14 +771,14 @@ public List calculateInterestUsing(final MathContext mc, final Lo private LocalDate interestPostingUpToDate(final LocalDate interestPostingDate) { LocalDate interestPostingUpToDate = interestPostingDate; final LocalDate uptoMaturityDate = interestCalculatedUpto(); - if (uptoMaturityDate != null && uptoMaturityDate.isBefore(interestPostingDate)) { + if (uptoMaturityDate != null && DateUtils.isBefore(uptoMaturityDate, interestPostingDate)) { interestPostingUpToDate = uptoMaturityDate; } return interestPostingUpToDate; } public LocalDate maturityDate() { - return this.accountTermAndPreClosure.getMaturityLocalDate(); + return this.accountTermAndPreClosure.getMaturityDate(); } public BigDecimal maturityAmount() { @@ -813,11 +807,10 @@ private Money totalInterestPosted() { } @Override - public Map activate(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { - - final Map actualChanges = super.activate(currentUser, command, tenantsTodayDate); + public Map activate(final AppUser currentUser, final JsonCommand command) { + final Map actualChanges = super.activate(currentUser, command); - if (accountTermAndPreClosure.isAfterExpectedFirstDepositDate(getActivationLocalDate())) { + if (accountTermAndPreClosure.isAfterExpectedFirstDepositDate(getActivationDate())) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME); @@ -889,13 +882,12 @@ public SavingsAccountTransaction deposit(final SavingsAccountTransactionDTO tran } public void handleScheduleInstallments(final SavingsAccountTransaction transaction) { - - final LocalDate transactionDate = transaction.transactionLocalDate(); + final LocalDate transactionDate = transaction.getTransactionDate(); Money transactionAmountUnprocessed = transaction.getAmount(getCurrency()); for (RecurringDepositScheduleInstallment currentInstallment : depositScheduleInstallments()) { if (currentInstallment.isNotFullyPaidOff() && transactionAmountUnprocessed.isGreaterThanZero()) { - if (!this.adjustAdvanceTowardsFuturePayments() && currentInstallment.dueDate().isAfter(transactionDate)) { + if (!this.adjustAdvanceTowardsFuturePayments() && DateUtils.isBefore(transactionDate, currentInstallment.dueDate())) { transactionAmountUnprocessed = Money.zero(getCurrency()); } transactionAmountUnprocessed = handleInstallmentTransaction(currentInstallment, transactionAmountUnprocessed, @@ -906,7 +898,6 @@ public void handleScheduleInstallments(final SavingsAccountTransaction transacti } public void updateScheduleInstallments() { - // reset all installments to process from the beginning for (RecurringDepositScheduleInstallment currentInstallment : depositScheduleInstallments()) { currentInstallment.resetDerivedFields(); @@ -923,8 +914,7 @@ public void updateScheduleInstallmentsWithNewRecommendedDepositAmount(BigDecimal // reset all installments to process from the beginning, also update // deposit amount as necessary for (RecurringDepositScheduleInstallment currentInstallment : depositScheduleInstallments()) { - if (currentInstallment.dueDate().isAfter(depositAmountupdatedFromDate) - || currentInstallment.dueDate().isEqual(depositAmountupdatedFromDate)) { + if (!DateUtils.isAfter(depositAmountupdatedFromDate, currentInstallment.dueDate())) { currentInstallment.updateDepositAmountAndResetDerivedFields(newDepositAmount); } else { currentInstallment.resetDerivedFields(); @@ -959,19 +949,14 @@ private List retreiveOrderedDepositTransactions() { */ protected boolean isTransactionInAdvanceOfInstallment(final int currentInstallmentIndex, final List installments, final LocalDate transactionDate) { - final RecurringDepositScheduleInstallment currentInstallment = installments.get(currentInstallmentIndex); - - return transactionDate.isBefore(currentInstallment.dueDate()); + return DateUtils.isBefore(transactionDate, currentInstallment.dueDate()); } private Money handleInstallmentTransaction(final RecurringDepositScheduleInstallment currentInstallment, final Money transactionAmountUnprocessed, final LocalDate transactionDate) { - Money transactionAmountRemaining = transactionAmountUnprocessed; - Money depositAmountPortion = Money.zero(transactionAmountRemaining.getCurrency()); - - depositAmountPortion = currentInstallment.payInstallment(transactionDate, transactionAmountRemaining); + Money depositAmountPortion = currentInstallment.payInstallment(transactionDate, transactionAmountRemaining); transactionAmountRemaining = transactionAmountRemaining.minus(depositAmountPortion); return transactionAmountRemaining; @@ -984,11 +969,11 @@ private boolean isAccountMatured() { private boolean isBeforeMaturityDate(final LocalDate compareDate) { final LocalDate maturityDate = this.maturityDate(); - return maturityDate == null ? true : compareDate.isBefore(maturityDate); + return maturityDate == null || DateUtils.isBefore(compareDate, maturityDate); } private boolean isBeforeDepositStartDate(LocalDate compareDate) { - return compareDate.isBefore(depositStartDate()); + return DateUtils.isBefore(compareDate, depositStartDate()); } public void validateDomainRules() { @@ -1003,7 +988,6 @@ public void validateDomainRules() { } private void validateDomainRules(final DataValidatorBuilder baseDataValidator) { - final boolean isMinTermGreaterThanMax = this.accountTermAndPreClosure.depositTermDetail() .isMinDepositTermGreaterThanMaxDepositTerm(); // deposit period should be within min and max deposit term @@ -1063,8 +1047,8 @@ public void validateApplicableInterestRate() { .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME); LocalDate maturityDate = calculateMaturityDate(); if (this.chart != null) { - final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate(); - LocalDate chartEndDate = this.chart.getEndDateAsLocalDate(); + final LocalDate chartFromDate = this.chart.getFromDate(); + LocalDate chartEndDate = this.chart.getEndDate(); chartEndDate = chartEndDate == null ? DateUtils.getBusinessLocalDate() : chartEndDate; final LocalDateInterval chartInterval = LocalDateInterval.create(chartFromDate, chartEndDate); @@ -1080,7 +1064,7 @@ public void validateApplicableInterestRate() { BigDecimal applicableInterestRate = this.chart.getApplicableInterestRate(maturityAmount, depositStartDate(), maturityDate, this.client); - if (applicableInterestRate.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE : Boolean.FALSE) { + if (applicableInterestRate.compareTo(BigDecimal.ZERO) == 0) { baseDataValidator.reset() .failWithCodeNoParameterAddedToErrorCode("no.applicable.interest.rate.is.found.based.on.amount.and.deposit.period"); } @@ -1092,13 +1076,13 @@ public void validateApplicableInterestRate() { if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } - /** + /* * final boolean recurringFrequencyBeforeDepositPeriod = recurringFrequencyBeforeDepositPeriod(); * * if (!recurringFrequencyBeforeDepositPeriod) { * baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode( * "recurring.frequency.not.before.deposit.period"); } - **/ + */ } public boolean isReinvestOnClosure() { @@ -1151,10 +1135,8 @@ accountNumber, externalId, accountType, getClosedOnDate(), closedBy, interestRat private boolean firstDepositDateBeforeAccountSubmittedOrActivationDate() { final LocalDate expectedFirstDepositLocalDate = accountTermAndPreClosure.getExpectedFirstDepositOnDate(); - if (expectedFirstDepositLocalDate == null) { - return false; - } - return expectedFirstDepositLocalDate.isBefore(accountSubmittedOrActivationDate()); + return expectedFirstDepositLocalDate != null + && DateUtils.isBefore(expectedFirstDepositLocalDate, accountSubmittedOrActivationDate()); } public void setDatesFrom(final LocalDate now) { @@ -1192,7 +1174,7 @@ public void generateSchedule(final PeriodFrequencyType frequency, final Integer int installmentNumber = 1; final LocalDate maturityDate = calcualteScheduleTillDate(frequency, recurringEvery); final BigDecimal depositAmount = this.recurringDetail.mandatoryRecommendedDepositAmount(); - while (maturityDate.isAfter(installmentDate)) { + while (DateUtils.isBefore(installmentDate, maturityDate)) { final RecurringDepositScheduleInstallment installment = RecurringDepositScheduleInstallment.installment(this, installmentNumber, installmentDate, depositAmount); addDepositScheduleInstallment(installment); @@ -1226,7 +1208,7 @@ public boolean isCalendarInherited() { public void updateOverduePayments(final LocalDate todayDate) { LocalDate overdueUptoDate = this.maturityDate(); - if (overdueUptoDate == null || overdueUptoDate.isAfter(todayDate)) { + if (overdueUptoDate == null || DateUtils.isAfter(overdueUptoDate, todayDate)) { overdueUptoDate = todayDate; } @@ -1234,7 +1216,7 @@ public void updateOverduePayments(final LocalDate todayDate) { int noOfOverdueInstallments = 0; Money totalOverdueAmount = Money.zero(getCurrency()); for (RecurringDepositScheduleInstallment installment : installments) { - if (installment.isNotFullyPaidOff() && overdueUptoDate.isAfter(installment.dueDate())) { + if (installment.isNotFullyPaidOff() && DateUtils.isAfter(overdueUptoDate, installment.dueDate())) { noOfOverdueInstallments++; totalOverdueAmount = totalOverdueAmount.plus(installment.getDepositAmountOutstanding(getCurrency())); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositScheduleInstallment.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositScheduleInstallment.java index b332a4b2e8d..eef970f8dfb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositScheduleInstallment.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositScheduleInstallment.java @@ -18,6 +18,8 @@ */ package org.apache.fineract.portfolio.savings.domain; +import static org.apache.fineract.infrastructure.core.service.DateUtils.getSystemZoneId; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.JoinColumn; @@ -25,13 +27,17 @@ import jakarta.persistence.Table; import java.math.BigDecimal; import java.time.LocalDate; -import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.Optional; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @Entity @Table(name = "m_mandatory_savings_schedule") -public class RecurringDepositScheduleInstallment extends AbstractAuditableCustom { +public class RecurringDepositScheduleInstallment extends AbstractAuditableWithUTCDateTimeCustom { @ManyToOne(optional = false) @JoinColumn(name = "savings_account_id") @@ -64,15 +70,18 @@ public class RecurringDepositScheduleInstallment extends AbstractAuditableCustom @Column(name = "obligations_met_on_date") private LocalDate obligationsMetOnDate; + @Deprecated + @Column(name = "created_date") + private LocalDateTime createdDateToRemove; + + @Deprecated + @Column(name = "lastmodified_date") + private LocalDateTime lastModifiedDateToRemove; + /** * */ - protected RecurringDepositScheduleInstallment() { - this.installmentNumber = null; - this.fromDate = null; - this.dueDate = null; - this.obligationsMet = false; - } + protected RecurringDepositScheduleInstallment() {} /** * @param account @@ -165,6 +174,24 @@ public LocalDate dueDate() { return this.dueDate; } + public Integer installmentNumber() { + return this.installmentNumber; + } + + @Override + public Optional getCreatedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getCreatedDate() + .orElse(createdDateToRemove == null ? null : createdDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); + } + + @Override + public Optional getLastModifiedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getLastModifiedDate() + .orElse(lastModifiedDateToRemove == null ? null : lastModifiedDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); + } + public Money payInstallment(final LocalDate transactionDate, final Money transactionAmountRemaining) { final MonetaryCurrency currency = transactionAmountRemaining.getCurrency(); @@ -209,11 +236,11 @@ private void trackAdvanceAndLateTotalsForInstallment(final LocalDate transaction } private boolean isInAdvance(final LocalDate transactionDate) { - return transactionDate.isBefore(dueDate()); + return DateUtils.isBefore(transactionDate, dueDate()); } private boolean isLatePayment(final LocalDate transactionDate) { - return transactionDate.isAfter(dueDate()); + return DateUtils.isAfter(transactionDate, dueDate()); } private Money asMoney(final BigDecimal decimal, final MonetaryCurrency currency) { @@ -232,8 +259,4 @@ public void updateDepositAmountAndResetDerivedFields(BigDecimal newDepositAmount this.depositAmount = newDepositAmount; this.resetDerivedFields(); } - - public Integer installmentNumber() { - return this.installmentNumber; - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java index f9e1d7975f5..5abf3857e83 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java @@ -77,7 +77,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; -import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.domain.LocalDateInterval; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; @@ -133,7 +133,7 @@ @DiscriminatorColumn(name = "deposit_type_enum", discriminatorType = DiscriminatorType.INTEGER) @DiscriminatorValue("100") @SuppressWarnings({ "MemberName" }) -public class SavingsAccount extends AbstractPersistableCustom { +public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom { private static final Logger LOG = LoggerFactory.getLogger(SavingsAccount.class); @@ -528,11 +528,10 @@ public void postInterest(final MathContext mc, final LocalDate interestPostingUp } for (final PostingPeriod interestPostingPeriod : postingPeriods) { - final LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); - if (!interestPostingTransactionDate.isAfter(interestPostingUpToDate)) { + if (!DateUtils.isAfter(interestPostingTransactionDate, interestPostingUpToDate)) { interestPostedToDate = interestPostedToDate.plus(interestEarnedToBePostedForPeriod); SavingsAccountTransaction postingTransaction = null; @@ -725,19 +724,19 @@ protected boolean createWithHoldTransaction(final BigDecimal amount, final Local protected boolean updateWithHoldTransaction(final BigDecimal amount, final SavingsAccountTransaction withholdTransaction) { boolean isTaxAdded = false; if (this.taxGroup != null && amount.compareTo(BigDecimal.ZERO) > 0) { - Map taxSplit = TaxUtils.splitTax(amount, withholdTransaction.transactionLocalDate(), + Map taxSplit = TaxUtils.splitTax(amount, withholdTransaction.getTransactionDate(), this.taxGroup.getTaxGroupMappings(), amount.scale()); BigDecimal totalTax = TaxUtils.totalTaxAmount(taxSplit); if (totalTax.compareTo(BigDecimal.ZERO) > 0) { if (withholdTransaction.getId() == null) { - withholdTransaction.updateAmount(Money.of(currency, totalTax)); + withholdTransaction.setAmount(Money.of(currency, totalTax)); withholdTransaction.getTaxDetails().clear(); SavingsAccountTransaction.updateTaxDetails(taxSplit, withholdTransaction); isTaxAdded = true; } else if (totalTax.compareTo(withholdTransaction.getAmount()) != 0) { withholdTransaction.reverse(); SavingsAccountTransaction newWithholdTransaction = SavingsAccountTransaction.withHoldTax(this, office(), - withholdTransaction.transactionLocalDate(), Money.of(currency, totalTax), taxSplit); + withholdTransaction.getTransactionDate(), Money.of(currency, totalTax), taxSplit); addTransaction(newWithholdTransaction); isTaxAdded = true; } @@ -777,7 +776,7 @@ public List getManualPostingDates() { List transactions = new ArrayList<>(); for (SavingsAccountTransaction trans : this.transactions) { if (trans.isInterestPosting() && trans.isNotReversed() && !trans.isReversalTransaction() && trans.isManualTransaction()) { - transactions.add(trans.getTransactionLocalDate()); + transactions.add(trans.getTransactionDate()); } } return transactions; @@ -787,7 +786,7 @@ public List getManualPostingDatesWithPivotConfig() { List transactions = new ArrayList<>(); for (SavingsAccountTransaction trans : this.savingsAccountTransactions) { if (trans.isInterestPosting() && trans.isNotReversed() && trans.isManualTransaction()) { - transactions.add(trans.getTransactionLocalDate()); + transactions.add(trans.getTransactionDate()); } } return transactions; @@ -856,7 +855,7 @@ public List calculateInterestUsing(final MathContext mc, final Lo final List allPostingPeriods = new ArrayList<>(); Money periodStartingBalance; - if (this.startInterestCalculationDate != null && !this.getStartInterestCalculationDate().equals(this.getActivationLocalDate())) { + if (this.startInterestCalculationDate != null && !this.getStartInterestCalculationDate().equals(this.getActivationDate())) { LocalDate startInterestCalculationDate = this.startInterestCalculationDate; SavingsAccountTransaction transaction = null; if (backdatedTxnsAllowedTill) { @@ -910,7 +909,7 @@ public List calculateInterestUsing(final MathContext mc, final Lo allPostingPeriods.add(postingPeriod); } - this.savingsHelper.calculateInterestForAllPostingPeriods(this.currency, allPostingPeriods, getLockedInUntilLocalDate(), + this.savingsHelper.calculateInterestForAllPostingPeriods(this.currency, allPostingPeriods, getLockedInUntilDate(), isTransferInterestToOtherAccount()); this.summary.updateFromInterestPeriodSummaries(this.currency, allPostingPeriods); @@ -1018,15 +1017,15 @@ protected void recalculateDailyBalances(final Money openingAccountBalance, final } runningBalance = runningBalance.plus(transactionAmount); - if (!transaction.getRunningBalance(transactionAmount.getCurrency()).isEqualTo(transactionAmount)) { - transaction.updateRunningBalance(runningBalance); + if (!transaction.getRunningBalance(this.currency).isEqualTo(transactionAmount)) { + transaction.setRunningBalance(runningBalance); } if (overdraftAmount.isZero() && runningBalance.isLessThanZero() && !transaction.isAmountOnHold()) { overdraftAmount = overdraftAmount.plus(runningBalance.getAmount().negate()); } if (transaction.getId() == null && overdraftAmount.isGreaterThanZero()) { - transaction.updateOverdraftAmount(overdraftAmount.getAmount()); - } else if (overdraftAmount.isNotEqualTo(transaction.getOverdraftAmount(getCurrency()))) { + transaction.setOverdraftAmount(overdraftAmount); + } else if (overdraftAmount.isNotEqualTo(transaction.getOverdraftAmount(this.currency))) { SavingsAccountTransaction accountTransaction = SavingsAccountTransaction.copyTransaction(transaction); if (transaction.isChargeTransaction()) { Set chargesPaidBy = transaction.getSavingsAccountChargesPaid(); @@ -1041,9 +1040,9 @@ protected void recalculateDailyBalances(final Money openingAccountBalance, final reversal = SavingsAccountTransaction.reversal(transaction); } if (overdraftAmount.isGreaterThanZero()) { - accountTransaction.updateOverdraftAmount(overdraftAmount.getAmount()); + accountTransaction.setOverdraftAmount(overdraftAmount); } - accountTransaction.updateRunningBalance(runningBalance); + accountTransaction.setRunningBalance(runningBalance); if (backdatedTxnsAllowedTill) { addTransactionToExisting(accountTransaction); if (reversal != null) { @@ -1082,7 +1081,7 @@ protected void resetAccountTransactionsEndOfDayBalances(final List dataValidationErrors = new ArrayList<>(); dataValidationErrors.add(error); @@ -1279,14 +1276,13 @@ public SavingsAccountTransaction withdraw(final SavingsAccountTransactionDTO tra if (applyWithdrawFee) { // auto pay withdrawal fee - payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate(), transactionDTO.getAppUser(), - transactionDTO.getPaymentDetail(), backdatedTxnsAllowedTill, refNo); + payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate(), transactionDTO.getPaymentDetail(), + backdatedTxnsAllowedTill, refNo); } final Money transactionAmountMoney = Money.of(this.currency, transactionDTO.getTransactionAmount()); final SavingsAccountTransaction transaction = SavingsAccountTransaction.withdrawal(this, office(), - transactionDTO.getPaymentDetail(), transactionDTO.getTransactionDate(), transactionAmountMoney, - transactionDTO.getCreatedDate(), transactionDTO.getAppUser(), refNo); + transactionDTO.getPaymentDetail(), transactionDTO.getTransactionDate(), transactionAmountMoney, refNo); if (backdatedTxnsAllowedTill) { addTransactionToExisting(transaction); @@ -1317,10 +1313,9 @@ public BigDecimal calculateWithdrawalFee(final BigDecimal transactionAmount) { return result; } - private void payWithdrawalFee(final BigDecimal transactionAmount, final LocalDate transactionDate, final AppUser user, - final PaymentDetail paymentDetail, final boolean backdatedTxnsAllowedTill, final String refNo) { + private void payWithdrawalFee(final BigDecimal transactionAmount, final LocalDate transactionDate, final PaymentDetail paymentDetail, + final boolean backdatedTxnsAllowedTill, final String refNo) { for (SavingsAccountCharge charge : this.charges()) { - if (charge.isWithdrawalFee() && charge.isActive()) { if (charge.getFreeWithdrawalCount() == null) { @@ -1330,32 +1325,30 @@ private void payWithdrawalFee(final BigDecimal transactionAmount, final LocalDat if (charge.isEnablePaymentType() && charge.isEnableFreeWithdrawal()) { // discount transaction to // specific paymentType if (paymentDetail.getPaymentType().getName().equals(charge.getCharge().getPaymentType().getName())) { - resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, user, refNo); + resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, refNo); } } else if (charge.isEnablePaymentType()) { // normal charge-transaction to specific paymentType if (paymentDetail.getPaymentType().getName().equals(charge.getCharge().getPaymentType().getName())) { charge.updateWithdralFeeAmount(transactionAmount); - this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user, - backdatedTxnsAllowedTill, refNo); + this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, backdatedTxnsAllowedTill, + refNo); } } else if (!charge.isEnablePaymentType() && charge.isEnableFreeWithdrawal()) { // discount transaction // irrespective of // PaymentTypes. - resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, user, refNo); + resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, refNo); } else { // normal-withdraw charge.updateWithdralFeeAmount(transactionAmount); - this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user, backdatedTxnsAllowedTill, + this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, backdatedTxnsAllowedTill, refNo); } - } - } } private void resetFreeChargeDaysCount(SavingsAccountCharge charge, final BigDecimal transactionAmount, final LocalDate transactionDate, - final AppUser user, final String refNo) { + final String refNo) { LocalDate resetDate = charge.getResetChargeDate(); Integer restartPeriod = charge.getRestartFrequency(); @@ -1374,12 +1367,12 @@ private void resetFreeChargeDaysCount(SavingsAccountCharge charge, final BigDeci YearMonth gapYearMonth = YearMonth.from(gapIntervalMonth); YearMonth localYearMonth = YearMonth.from(localDate); if (localYearMonth.isBefore(gapYearMonth)) { - countValidation(charge, transactionAmount, transactionDate, user, refNo); + countValidation(charge, transactionAmount, transactionDate, refNo); } else { discountCharge(1, charge); } } else { // calculation for days - Long completedDays; + long completedDays; if (resetDate == null) { completedDays = DAYS.between(DateUtils.getBusinessLocalDate(), this.activatedOnDate); @@ -1388,10 +1381,10 @@ private void resetFreeChargeDaysCount(SavingsAccountCharge charge, final BigDeci completedDays = DAYS.between(DateUtils.getBusinessLocalDate(), resetDate); } - int totalDays = completedDays.intValue(); + int totalDays = (int) completedDays; if (totalDays < restartPeriod) { - countValidation(charge, transactionAmount, transactionDate, user, refNo); + countValidation(charge, transactionAmount, transactionDate, refNo); } else { discountCharge(1, charge); } @@ -1399,7 +1392,7 @@ private void resetFreeChargeDaysCount(SavingsAccountCharge charge, final BigDeci } private void countValidation(SavingsAccountCharge charge, final BigDecimal transactionAmount, final LocalDate transactionDate, - final AppUser user, final String refNo) { + final String refNo) { boolean backdatedTxnsAllowedTill = false; if (charge.getFreeWithdrawalCount() < charge.getFrequencyFreeWithdrawalCharge()) { final Integer count = charge.getFreeWithdrawalCount() + 1; @@ -1407,7 +1400,7 @@ private void countValidation(SavingsAccountCharge charge, final BigDecimal trans charge.updateNoWithdrawalFee(); } else { charge.updateWithdralFeeAmount(transactionAmount); - this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user, backdatedTxnsAllowedTill, refNo); + this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, backdatedTxnsAllowedTill, refNo); } } @@ -1433,8 +1426,7 @@ public boolean isBeforeLastPostingPeriod(final LocalDate transactionDate, final if (this.summary.getInterestPostedTillDate() == null) { return false; } - - transactionBeforeLastInterestPosting = this.summary.getInterestPostedTillDate().isAfter(transactionDate); + transactionBeforeLastInterestPosting = DateUtils.isBefore(transactionDate, this.summary.getInterestPostedTillDate()); } return transactionBeforeLastInterestPosting; @@ -1475,13 +1467,12 @@ public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transac if (depositAccountOnHoldTransactions != null) { for (final DepositAccountOnHoldTransaction onHoldTransaction : depositAccountOnHoldTransactions) { // Compare the balance of the on hold: - if ((onHoldTransaction.getTransactionDate().isBefore(transaction.transactionLocalDate()) - || onHoldTransaction.getTransactionDate().isEqual(transaction.transactionLocalDate())) - && (lastSavingsDate == null || onHoldTransaction.getTransactionDate().isAfter(lastSavingsDate))) { + if (!DateUtils.isAfter(onHoldTransaction.getTransactionDate(), transaction.getTransactionDate()) + && (lastSavingsDate == null || DateUtils.isAfter(onHoldTransaction.getTransactionDate(), lastSavingsDate))) { if (onHoldTransaction.getTransactionType().isHold()) { - minRequiredBalance = minRequiredBalance.plus(onHoldTransaction.getAmountMoney(this.currency)); + minRequiredBalance = minRequiredBalance.plus(onHoldTransaction.getAmount(this.currency)); } else { - minRequiredBalance = minRequiredBalance.minus(onHoldTransaction.getAmountMoney(this.currency)); + minRequiredBalance = minRequiredBalance.minus(onHoldTransaction.getAmount(this.currency)); } } } @@ -1495,7 +1486,7 @@ public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transac transactionAmount); } } - lastSavingsDate = transaction.transactionLocalDate(); + lastSavingsDate = transaction.getTransactionDate(); } @@ -1558,13 +1549,12 @@ public void validateAccountBalanceDoesNotBecomeNegative(final String transaction if (depositAccountOnHoldTransactions != null) { for (final DepositAccountOnHoldTransaction onHoldTransaction : depositAccountOnHoldTransactions) { // Compare the balance of the on hold: - if ((onHoldTransaction.getTransactionDate().isBefore(transaction.transactionLocalDate()) - || onHoldTransaction.getTransactionDate().isEqual(transaction.transactionLocalDate())) - && (lastSavingsDate == null || onHoldTransaction.getTransactionDate().isAfter(lastSavingsDate))) { + if (!DateUtils.isAfter(onHoldTransaction.getTransactionDate(), transaction.getTransactionDate()) + && (lastSavingsDate == null || DateUtils.isAfter(onHoldTransaction.getTransactionDate(), lastSavingsDate))) { if (onHoldTransaction.getTransactionType().isHold()) { - minRequiredBalance = minRequiredBalance.plus(onHoldTransaction.getAmountMoney(this.currency)); + minRequiredBalance = minRequiredBalance.plus(onHoldTransaction.getAmount(this.currency)); } else { - minRequiredBalance = minRequiredBalance.minus(onHoldTransaction.getAmountMoney(this.currency)); + minRequiredBalance = minRequiredBalance.minus(onHoldTransaction.getAmount(this.currency)); } } } @@ -1584,7 +1574,7 @@ public void validateAccountBalanceDoesNotBecomeNegative(final String transaction } } } - lastSavingsDate = transaction.transactionLocalDate(); + lastSavingsDate = transaction.getTransactionDate(); } BigDecimal withdrawalFee = null; @@ -1608,22 +1598,13 @@ public void validateAccountBalanceDoesNotViolateOverdraft(final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(resourceName + SavingsApiConstants.summitalAction); @@ -2252,17 +2204,17 @@ public void validateNewApplicationState(final LocalDate todayDateOfTenant, final throw new PlatformApiDataValidationException(dataValidationErrors); } - if (submittedOn.isAfter(todayDateOfTenant)) { + final LocalDate submittedOn = getSubmittedOnDate(); + if (DateUtils.isDateInTheFuture(submittedOn)) { baseDataValidator.reset().parameter(SavingsApiConstants.submittedOnDateParamName).value(submittedOn) .failWithCodeNoParameterAddedToErrorCode("cannot.be.a.future.date"); } if (this.client != null && this.client.isActivatedAfter(submittedOn)) { - baseDataValidator.reset().parameter(SavingsApiConstants.submittedOnDateParamName).value(this.client.getActivationLocalDate()) + baseDataValidator.reset().parameter(SavingsApiConstants.submittedOnDateParamName).value(this.client.getActivationDate()) .failWithCodeNoParameterAddedToErrorCode("cannot.be.before.client.activation.date"); } else if (this.group != null && this.group.isActivatedAfter(submittedOn)) { - - baseDataValidator.reset().parameter(SavingsApiConstants.submittedOnDateParamName).value(this.group.getActivationLocalDate()) + baseDataValidator.reset().parameter(SavingsApiConstants.submittedOnDateParamName).value(this.group.getActivationDate()) .failWithCodeNoParameterAddedToErrorCode("cannot.be.before.client.activation.date"); } @@ -2271,14 +2223,6 @@ public void validateNewApplicationState(final LocalDate todayDateOfTenant, final } } - protected LocalDate getSubmittedOnLocalDate() { - return this.submittedOnDate; - } - - private LocalDate getApprovedOnLocalDate() { - return this.approvedOnDate; - } - public Client getClient() { return this.client; } @@ -2303,8 +2247,7 @@ public BigDecimal getNominalAnnualInterestRateOverdraft() { return this.nominalAnnualInterestRateOverdraft; } - public Map approveApplication(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { - + public Map approveApplication(final AppUser currentUser, final JsonCommand command) { final Map actualChanges = new LinkedHashMap<>(); final List dataValidationErrors = new ArrayList<>(); @@ -2334,9 +2277,8 @@ public Map approveApplication(final AppUser currentUser, final J actualChanges.put(SavingsApiConstants.dateFormatParamName, command.dateFormat()); actualChanges.put(SavingsApiConstants.approvedOnDateParamName, approvedOnDateChange); - final LocalDate submittalDate = getSubmittedOnLocalDate(); - if (approvedOn.isBefore(submittalDate)) { - + final LocalDate submittalDate = getSubmittedOnDate(); + if (DateUtils.isBefore(approvedOn, submittalDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); final String submittalDateAsString = formatter.format(submittalDate); @@ -2347,9 +2289,7 @@ public Map approveApplication(final AppUser currentUser, final J throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (approvedOn.isAfter(tenantsTodayDate)) { - + if (DateUtils.isAfterBusinessDate(approvedOn)) { baseDataValidator.reset().parameter(SavingsApiConstants.approvedOnDateParamName) .failWithCodeNoParameterAddedToErrorCode("cannot.be.a.future.date"); @@ -2425,7 +2365,7 @@ public void undoTransaction(final Long transactionId) { } validateAttemptToUndoTransferRelatedTransactions(transactionToUndo); - validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.transactionLocalDate()); + validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.getTransactionDate()); transactionToUndo.reverse(); if (transactionToUndo.isChargeTransaction() || transactionToUndo.isWaiveCharge()) { // undo charge @@ -2455,7 +2395,7 @@ public void undoSavingsTransaction(final Long transactionId) { } validateAttemptToUndoTransferRelatedTransactions(transactionToUndo); - validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.transactionLocalDate()); + validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.getTransactionDate()); transactionToUndo.reverse(); if (transactionToUndo.isChargeTransaction() || transactionToUndo.isWaiveCharge()) { // undo charge @@ -2463,9 +2403,9 @@ public void undoSavingsTransaction(final Long transactionId) { for (final SavingsAccountChargePaidBy savingsAccountChargePaidBy : chargesPaidBy) { final SavingsAccountCharge chargeToUndo = savingsAccountChargePaidBy.getSavingsAccountCharge(); if (transactionToUndo.isChargeTransaction()) { - chargeToUndo.undoPayment(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency())); + chargeToUndo.undoPayment(this.getCurrency(), transactionToUndo.getAmount(this.currency)); } else if (transactionToUndo.isWaiveCharge()) { - chargeToUndo.undoWaiver(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency())); + chargeToUndo.undoWaiver(this.getCurrency(), transactionToUndo.getAmount(this.currency)); } } } @@ -2478,7 +2418,7 @@ public void undoTransaction(final SavingsAccountTransaction transactionToUndo) { } validateAttemptToUndoTransferRelatedTransactions(transactionToUndo); - validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.transactionLocalDate()); + validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.getTransactionDate()); transactionToUndo.reverse(); if (transactionToUndo.isChargeTransaction() || transactionToUndo.isWaiveCharge()) { // undo charge @@ -2486,33 +2426,31 @@ public void undoTransaction(final SavingsAccountTransaction transactionToUndo) { for (final SavingsAccountChargePaidBy savingsAccountChargePaidBy : chargesPaidBy) { final SavingsAccountCharge chargeToUndo = savingsAccountChargePaidBy.getSavingsAccountCharge(); if (transactionToUndo.isChargeTransaction()) { - chargeToUndo.undoPayment(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency())); + chargeToUndo.undoPayment(this.getCurrency(), transactionToUndo.getAmount(this.currency)); } else if (transactionToUndo.isWaiveCharge()) { - chargeToUndo.undoWaiver(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency())); + chargeToUndo.undoWaiver(this.getCurrency(), transactionToUndo.getAmount(this.currency)); } } } } private LocalDate findLatestAnnualFeeTransactionDueDate() { - LocalDate nextDueDate = null; LocalDate lastAnnualFeeTransactionDate = null; for (final SavingsAccountTransaction transaction : retreiveOrderedNonInterestPostingTransactions()) { if (transaction.isAnnualFeeAndNotReversed()) { + LocalDate transactionDate = transaction.getTransactionDate(); if (lastAnnualFeeTransactionDate == null) { - lastAnnualFeeTransactionDate = transaction.transactionLocalDate(); + lastAnnualFeeTransactionDate = transactionDate; nextDueDate = lastAnnualFeeTransactionDate; } - - if (transaction.transactionLocalDate().isAfter(lastAnnualFeeTransactionDate)) { - lastAnnualFeeTransactionDate = transaction.transactionLocalDate(); + if (DateUtils.isAfter(transactionDate, lastAnnualFeeTransactionDate)) { + lastAnnualFeeTransactionDate = transactionDate; nextDueDate = lastAnnualFeeTransactionDate; } } } - return nextDueDate; } @@ -2539,8 +2477,7 @@ public void validateAccountBalanceDoesNotBecomeNegativeMinimal(final BigDecimal } } - public Map rejectApplication(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { - + public Map rejectApplication(final AppUser currentUser, final JsonCommand command) { final Map actualChanges = new LinkedHashMap<>(); final List dataValidationErrors = new ArrayList<>(); @@ -2576,10 +2513,8 @@ public Map rejectApplication(final AppUser currentUser, final Js actualChanges.put(SavingsApiConstants.rejectedOnDateParamName, rejectedOnAsString); actualChanges.put(SavingsApiConstants.closedOnDateParamName, rejectedOnAsString); - final LocalDate submittalDate = getSubmittedOnLocalDate(); - - if (rejectedOn.isBefore(submittalDate)) { - + final LocalDate submittalDate = getSubmittedOnDate(); + if (DateUtils.isBefore(rejectedOn, submittalDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); final String submittalDateAsString = formatter.format(submittalDate); @@ -2590,9 +2525,7 @@ public Map rejectApplication(final AppUser currentUser, final Js throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (rejectedOn.isAfter(tenantsTodayDate)) { - + if (DateUtils.isAfterBusinessDate(rejectedOn)) { baseDataValidator.reset().parameter(SavingsApiConstants.rejectedOnDateParamName).value(rejectedOn) .failWithCodeNoParameterAddedToErrorCode("cannot.be.a.future.date"); @@ -2605,8 +2538,7 @@ public Map rejectApplication(final AppUser currentUser, final Js return actualChanges; } - public Map applicantWithdrawsFromApplication(final AppUser currentUser, final JsonCommand command, - final LocalDate tenantsTodayDate) { + public Map applicantWithdrawsFromApplication(final AppUser currentUser, final JsonCommand command) { final Map actualChanges = new LinkedHashMap<>(); final List dataValidationErrors = new ArrayList<>(); @@ -2642,9 +2574,8 @@ public Map applicantWithdrawsFromApplication(final AppUser curre actualChanges.put(SavingsApiConstants.withdrawnOnDateParamName, withdrawnOnAsString); actualChanges.put(SavingsApiConstants.closedOnDateParamName, withdrawnOnAsString); - final LocalDate submittalDate = getSubmittedOnLocalDate(); - if (withdrawnOn.isBefore(submittalDate)) { - + final LocalDate submittalDate = getSubmittedOnDate(); + if (DateUtils.isBefore(withdrawnOn, submittalDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); final String submittalDateAsString = formatter.format(submittalDate); @@ -2655,9 +2586,7 @@ public Map applicantWithdrawsFromApplication(final AppUser curre throw new PlatformApiDataValidationException(dataValidationErrors); } } - - if (withdrawnOn.isAfter(tenantsTodayDate)) { - + if (DateUtils.isAfterBusinessDate(withdrawnOn)) { baseDataValidator.reset().parameter(SavingsApiConstants.withdrawnOnDateParamName).value(withdrawnOn) .failWithCodeNoParameterAddedToErrorCode("cannot.be.a.future.date"); @@ -2670,8 +2599,7 @@ public Map applicantWithdrawsFromApplication(final AppUser curre return actualChanges; } - public Map activate(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { - + public Map activate(final AppUser currentUser, final JsonCommand command) { final Map actualChanges = new LinkedHashMap<>(); final List dataValidationErrors = new ArrayList<>(); @@ -2707,14 +2635,14 @@ public Map activate(final AppUser currentUser, final JsonCommand this.closedBy = null; this.activatedOnDate = activationDate; this.activatedBy = currentUser; - this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate()); + this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationDate()); /* * if (annualFeeSettingsSet()) { updateToNextAnnualFeeDueDateFrom(getActivationLocalDate()); } */ if (this.client != null && this.client.isActivatedAfter(activationDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); - final String dateAsString = formatter.format(this.client.getActivationLocalDate()); + final String dateAsString = formatter.format(this.client.getActivationDate()); baseDataValidator.reset().parameter(SavingsApiConstants.activatedOnDateParamName).value(dateAsString) .failWithCodeNoParameterAddedToErrorCode("cannot.be.before.client.activation.date"); if (!dataValidationErrors.isEmpty()) { @@ -2724,7 +2652,7 @@ public Map activate(final AppUser currentUser, final JsonCommand if (this.group != null && this.group.isActivatedAfter(activationDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); - final String dateAsString = formatter.format(this.client.getActivationLocalDate()); + final String dateAsString = formatter.format(this.client.getActivationDate()); baseDataValidator.reset().parameter(SavingsApiConstants.activatedOnDateParamName).value(dateAsString) .failWithCodeNoParameterAddedToErrorCode("cannot.be.before.group.activation.date"); if (!dataValidationErrors.isEmpty()) { @@ -2732,9 +2660,8 @@ public Map activate(final AppUser currentUser, final JsonCommand } } - final LocalDate approvalDate = getApprovedOnLocalDate(); - if (activationDate.isBefore(approvalDate)) { - + final LocalDate approvalDate = getApprovedOnDate(); + if (DateUtils.isBefore(activationDate, approvalDate)) { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(command.extractLocale()); final String dateAsString = formatter.format(approvalDate); @@ -2746,8 +2673,7 @@ public Map activate(final AppUser currentUser, final JsonCommand } } - if (activationDate.isAfter(tenantsTodayDate)) { - + if (DateUtils.isAfterBusinessDate(activationDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.activatedOnDateParamName).value(activationDate) .failWithCodeNoParameterAddedToErrorCode("cannot.be.a.future.date"); @@ -2761,15 +2687,14 @@ public Map activate(final AppUser currentUser, final JsonCommand } public void processAccountUponActivation(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, - final Integer financialYearBeginningMonth, final AppUser user) { - + final Integer financialYearBeginningMonth) { // update annual fee due date for (SavingsAccountCharge charge : this.charges()) { - charge.updateToNextDueDateFrom(getActivationLocalDate()); + charge.updateToNextDueDateFrom(getActivationDate()); } // auto pay the activation time charges (No need of checking the pivot date config) - this.payActivationCharges(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, user, false); + this.payActivationCharges(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, false); // TODO : AA add activation charges to actual changes list } @@ -2789,18 +2714,18 @@ public void approveAndActivateApplication(final LocalDate appliedonDate, final A this.closedBy = null; this.activatedOnDate = appliedonDate; this.activatedBy = appliedBy; - this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate()); + this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationDate()); } private void payActivationCharges(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth, - final AppUser user, final boolean backdatedTxnsAllowedTill) { + final boolean backdatedTxnsAllowedTill) { boolean isSavingsChargeApplied = false; boolean postReversals = false; UUID refNo = UUID.randomUUID(); for (SavingsAccountCharge savingsAccountCharge : this.charges()) { if (savingsAccountCharge.isSavingsActivation()) { isSavingsChargeApplied = true; - payCharge(savingsAccountCharge, savingsAccountCharge.getAmountOutstanding(getCurrency()), getActivationLocalDate(), user, + payCharge(savingsAccountCharge, savingsAccountCharge.getAmountOutstanding(getCurrency()), getActivationDate(), backdatedTxnsAllowedTill, refNo.toString()); } } @@ -2809,7 +2734,7 @@ private void payActivationCharges(final boolean isSavingsInterestPostingAtCurren final MathContext mc = MathContext.DECIMAL64; boolean isInterestTransfer = false; LocalDate postInterestAsOnDate = null; - if (this.isBeforeLastPostingPeriod(getActivationLocalDate(), backdatedTxnsAllowedTill)) { + if (this.isBeforeLastPostingPeriod(getActivationDate(), backdatedTxnsAllowedTill)) { final LocalDate today = DateUtils.getBusinessLocalDate(); this.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestAsOnDate, backdatedTxnsAllowedTill, postReversals); @@ -2821,8 +2746,7 @@ private void payActivationCharges(final boolean isSavingsInterestPostingAtCurren } } - public Map close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { - + public Map close(final AppUser currentUser, final JsonCommand command) { final Map actualChanges = new LinkedHashMap<>(); final List dataValidationErrors = new ArrayList<>(); @@ -2841,14 +2765,14 @@ public Map close(final AppUser currentUser, final JsonCommand co final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); - if (closedDate.isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(closedDate, getActivationDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - if (closedDate.isAfter(tenantsTodayDate)) { + if (DateUtils.isAfterBusinessDate(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { @@ -2890,9 +2814,9 @@ public Map close(final AppUser currentUser, final JsonCommand co } protected void validateActivityNotBeforeClientOrGroupTransferDate(final SavingsEvent event, final LocalDate activityDate) { - if (this.client != null && this.client.getOfficeJoiningLocalDate() != null) { - final LocalDate clientOfficeJoiningDate = this.client.getOfficeJoiningLocalDate(); - if (activityDate.isBefore(clientOfficeJoiningDate)) { + if (this.client != null) { + final LocalDate clientOfficeJoiningDate = this.client.getOfficeJoiningDate(); + if (DateUtils.isBefore(activityDate, clientOfficeJoiningDate)) { throw new SavingsActivityPriorToClientTransferException(event.toString(), clientOfficeJoiningDate); } } @@ -3022,8 +2946,7 @@ public void removeCharge(final SavingsAccountCharge charge) { this.charges.remove(charge); } - public void waiveCharge(final Long savingsAccountChargeId, final AppUser user, final boolean backdatedTxnsAllowedTill) { - + public void waiveCharge(final Long savingsAccountChargeId, final boolean backdatedTxnsAllowedTill) { final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(SAVINGS_ACCOUNT_RESOURCE_NAME); @@ -3073,8 +2996,7 @@ public void waiveCharge(final Long savingsAccountChargeId, final AppUser user, f // waive charge final Money amountWaived = savingsAccountCharge.waive(getCurrency()); - handleWaiverChargeTransactions(savingsAccountCharge, amountWaived, user, backdatedTxnsAllowedTill); - + handleWaiverChargeTransactions(savingsAccountCharge, amountWaived, backdatedTxnsAllowedTill); } public void addCharge(final DateTimeFormatter formatter, final SavingsAccountCharge savingsAccountCharge, @@ -3099,15 +3021,15 @@ public void addCharge(final DateTimeFormatter formatter, final SavingsAccountCha } } - final LocalDate chargeDueDate = savingsAccountCharge.getDueLocalDate(); + final LocalDate chargeDueDate = savingsAccountCharge.getDueDate(); if (savingsAccountCharge.isOnSpecifiedDueDate()) { - if (getActivationLocalDate() != null && chargeDueDate.isBefore(getActivationLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().format(formatter)) + if (DateUtils.isBefore(chargeDueDate, getActivationDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationDate().format(formatter)) .failWithCodeNoParameterAddedToErrorCode("before.activationDate"); throw new PlatformApiDataValidationException(dataValidationErrors); - } else if (getSubmittedOnLocalDate() != null && chargeDueDate.isBefore(getSubmittedOnLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnLocalDate().format(formatter)) + } else if (DateUtils.isBefore(chargeDueDate, getSubmittedOnDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnDate().format(formatter)) .failWithCodeNoParameterAddedToErrorCode("before.submittedOnDate"); throw new PlatformApiDataValidationException(dataValidationErrors); } @@ -3130,9 +3052,9 @@ public void addCharge(final DateTimeFormatter formatter, final SavingsAccountCha if (savingsAccountCharge.isAnnualFee() || savingsAccountCharge.isMonthlyFee() || savingsAccountCharge.isWeeklyFee()) { // update due date if (isActive()) { - savingsAccountCharge.updateToNextDueDateFrom(getActivationLocalDate()); + savingsAccountCharge.updateToNextDueDateFrom(getActivationDate()); } else if (isApproved()) { - savingsAccountCharge.updateToNextDueDateFrom(getApprovedOnLocalDate()); + savingsAccountCharge.updateToNextDueDateFrom(getApprovedOnDate()); } } @@ -3156,9 +3078,8 @@ private boolean isAnnualFeeExists() { } public SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAccountCharge, final BigDecimal amountPaid, - final LocalDate transactionDate, final DateTimeFormatter formatter, final AppUser user, final boolean backdatedTxnsAllowedTill, + final LocalDate transactionDate, final DateTimeFormatter formatter, final boolean backdatedTxnsAllowedTill, final String refNo) { - final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(SAVINGS_ACCOUNT_RESOURCE_NAME); @@ -3184,8 +3105,8 @@ public SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAcc } } - if (getActivationLocalDate() != null && transactionDate.isBefore(getActivationLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().format(formatter)) + if (DateUtils.isBefore(transactionDate, getActivationDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationDate().format(formatter)) .failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate"); throw new PlatformApiDataValidationException(dataValidationErrors); } @@ -3203,19 +3124,19 @@ public SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAcc } if (savingsAccountCharge.isAnnualFee()) { - final LocalDate annualFeeDueDate = savingsAccountCharge.getDueLocalDate(); + final LocalDate annualFeeDueDate = savingsAccountCharge.getDueDate(); if (annualFeeDueDate == null) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.annualfee.settings"); throw new PlatformApiDataValidationException(dataValidationErrors); } - if (!annualFeeDueDate.equals(transactionDate)) { + if (!DateUtils.isEqual(annualFeeDueDate, transactionDate)) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("invalid.date"); throw new PlatformApiDataValidationException(dataValidationErrors); } LocalDate currentAnnualFeeNextDueDate = findLatestAnnualFeeTransactionDueDate(); - if (currentAnnualFeeNextDueDate != null && currentAnnualFeeNextDueDate.isEqual(transactionDate)) { + if (DateUtils.isEqual(currentAnnualFeeNextDueDate, transactionDate)) { baseDataValidator.reset().parameter("dueDate").value(transactionDate.format(formatter)) .failWithCodeNoParameterAddedToErrorCode("transaction.exists.on.date"); @@ -3244,35 +3165,35 @@ public SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAcc } } - return this.payCharge(savingsAccountCharge, chargePaid, transactionDate, user, backdatedTxnsAllowedTill, refNo); + return this.payCharge(savingsAccountCharge, chargePaid, transactionDate, backdatedTxnsAllowedTill, refNo); } public SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAccountCharge, final Money amountPaid, - final LocalDate transactionDate, final AppUser user, final boolean backdatedTxnsAllowedTill, String refNo) { + final LocalDate transactionDate, final boolean backdatedTxnsAllowedTill, String refNo) { savingsAccountCharge.pay(getCurrency(), amountPaid); - return handlePayChargeTransactions(savingsAccountCharge, amountPaid, transactionDate, user, backdatedTxnsAllowedTill, refNo); + return handlePayChargeTransactions(savingsAccountCharge, amountPaid, transactionDate, backdatedTxnsAllowedTill, refNo); } private SavingsAccountTransaction handlePayChargeTransactions(SavingsAccountCharge savingsAccountCharge, Money transactionAmount, - final LocalDate transactionDate, final AppUser user, final boolean backdatedTxnsAllowedTill, final String refNo) { - SavingsAccountTransaction chargeTransaction = null; + final LocalDate transactionDate, final boolean backdatedTxnsAllowedTill, final String refNo) { + SavingsAccountTransaction chargeTransaction; if (savingsAccountCharge.isWithdrawalFee()) { - chargeTransaction = SavingsAccountTransaction.withdrawalFee(this, office(), transactionDate, transactionAmount, user, refNo); + chargeTransaction = SavingsAccountTransaction.withdrawalFee(this, office(), transactionDate, transactionAmount, refNo); } else if (savingsAccountCharge.isAnnualFee()) { - chargeTransaction = SavingsAccountTransaction.annualFee(this, office(), transactionDate, transactionAmount, user); + chargeTransaction = SavingsAccountTransaction.annualFee(this, office(), transactionDate, transactionAmount); } else { - chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate, transactionAmount, user); + chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate, transactionAmount); } handleChargeTransactions(savingsAccountCharge, chargeTransaction, backdatedTxnsAllowedTill); return chargeTransaction; } - private void handleWaiverChargeTransactions(SavingsAccountCharge savingsAccountCharge, Money transactionAmount, AppUser user, + private void handleWaiverChargeTransactions(SavingsAccountCharge savingsAccountCharge, Money transactionAmount, boolean backdatedTxnsAllowedTill) { final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.waiver(this, office(), - DateUtils.getBusinessLocalDate(), transactionAmount, user); + DateUtils.getBusinessLocalDate(), transactionAmount); handleChargeTransactions(savingsAccountCharge, chargeTransaction, backdatedTxnsAllowedTill); } @@ -3281,7 +3202,7 @@ private void handleChargeTransactions(final SavingsAccountCharge savingsAccountC // Provide a link between transaction and savings charge for which // amount is waived. final SavingsAccountChargePaidBy chargePaidBy = SavingsAccountChargePaidBy.instance(transaction, savingsAccountCharge, - transaction.getAmount(this.getCurrency()).getAmount()); + transaction.getAmount(this.currency).getAmount()); transaction.getSavingsAccountChargesPaid().add(chargePaidBy); if (backdatedTxnsAllowedTill) { this.savingsAccountTransactions.add(transaction); @@ -3336,7 +3257,7 @@ public boolean allowOverdraft() { } public LocalDate accountSubmittedOrActivationDate() { - return getActivationLocalDate() == null ? getSubmittedOnLocalDate() : getActivationLocalDate(); + return getActivationDate() == null ? getSubmittedOnDate() : getActivationDate(); } public DepositAccountType depositAccountType() { @@ -3348,35 +3269,29 @@ protected boolean isTransferInterestToOtherAccount() { } public boolean accountSubmittedAndActivationOnSameDate() { - if (getSubmittedOnLocalDate() == null || getActivationLocalDate() == null) { - return false; - } - return getActivationLocalDate().isEqual(getSubmittedOnLocalDate()); + return getActivationDate() != null && DateUtils.isEqual(getActivationDate(), getSubmittedOnDate()); } public void validateInterestPostingAndCompoundingPeriodTypes(final DataValidatorBuilder baseDataValidator) { Map> postingtoCompoundMap = new HashMap<>(); - postingtoCompoundMap.put(SavingsPostingInterestPeriodType.DAILY, - Arrays.asList(new SavingsCompoundingInterestPeriodType[] { SavingsCompoundingInterestPeriodType.DAILY })); + postingtoCompoundMap.put(SavingsPostingInterestPeriodType.DAILY, Arrays.asList(SavingsCompoundingInterestPeriodType.DAILY)); - postingtoCompoundMap.put(SavingsPostingInterestPeriodType.MONTHLY, Arrays.asList(new SavingsCompoundingInterestPeriodType[] { - SavingsCompoundingInterestPeriodType.DAILY, SavingsCompoundingInterestPeriodType.MONTHLY })); + postingtoCompoundMap.put(SavingsPostingInterestPeriodType.MONTHLY, + Arrays.asList(SavingsCompoundingInterestPeriodType.DAILY, SavingsCompoundingInterestPeriodType.MONTHLY)); - postingtoCompoundMap.put(SavingsPostingInterestPeriodType.QUATERLY, - Arrays.asList(new SavingsCompoundingInterestPeriodType[] { SavingsCompoundingInterestPeriodType.DAILY, - SavingsCompoundingInterestPeriodType.MONTHLY, SavingsCompoundingInterestPeriodType.QUATERLY })); + postingtoCompoundMap.put(SavingsPostingInterestPeriodType.QUATERLY, Arrays.asList(SavingsCompoundingInterestPeriodType.DAILY, + SavingsCompoundingInterestPeriodType.MONTHLY, SavingsCompoundingInterestPeriodType.QUATERLY)); postingtoCompoundMap.put(SavingsPostingInterestPeriodType.BIANNUAL, - Arrays.asList(new SavingsCompoundingInterestPeriodType[] { SavingsCompoundingInterestPeriodType.DAILY, - SavingsCompoundingInterestPeriodType.MONTHLY, SavingsCompoundingInterestPeriodType.QUATERLY, - SavingsCompoundingInterestPeriodType.BI_ANNUAL })); + Arrays.asList(SavingsCompoundingInterestPeriodType.DAILY, SavingsCompoundingInterestPeriodType.MONTHLY, + SavingsCompoundingInterestPeriodType.QUATERLY, SavingsCompoundingInterestPeriodType.BI_ANNUAL)); postingtoCompoundMap.put(SavingsPostingInterestPeriodType.ANNUAL, - Arrays.asList(new SavingsCompoundingInterestPeriodType[] { SavingsCompoundingInterestPeriodType.DAILY, - SavingsCompoundingInterestPeriodType.MONTHLY, SavingsCompoundingInterestPeriodType.QUATERLY, - SavingsCompoundingInterestPeriodType.BI_ANNUAL, SavingsCompoundingInterestPeriodType.ANNUAL })); + Arrays.asList(SavingsCompoundingInterestPeriodType.DAILY, SavingsCompoundingInterestPeriodType.MONTHLY, + SavingsCompoundingInterestPeriodType.QUATERLY, SavingsCompoundingInterestPeriodType.BI_ANNUAL, + SavingsCompoundingInterestPeriodType.ANNUAL)); SavingsPostingInterestPeriodType savingsPostingInterestPeriodType = SavingsPostingInterestPeriodType .fromInt(interestPostingPeriodType); @@ -3431,7 +3346,7 @@ public boolean isTransactionAllowed(SavingsAccountTransactionType transactionTyp if (transactionDate == null) { return true; } - if (DateUtils.isDateInTheFuture(transactionDate) || transactionDate.isBefore(getActivationLocalDate())) { + if (DateUtils.isDateInTheFuture(transactionDate) || DateUtils.isBefore(transactionDate, getActivationDate())) { return false; } if (transactionType.isCredit()) { @@ -3545,14 +3460,14 @@ protected boolean applyWithholdTaxForDepositAccounts(final LocalDate interestPos return recalucateDailyBalance; } - public void setSubStatusInactive(AppUser appUser, final boolean backdatedTxnsAllowedTill) { + public void setSubStatusInactive(final boolean backdatedTxnsAllowedTill) { this.sub_status = SavingsAccountSubStatusEnum.INACTIVE.getValue(); LocalDate transactionDate = DateUtils.getBusinessLocalDate(); for (SavingsAccountCharge charge : this.charges()) { if (charge.isSavingsNoActivity() && charge.isActive()) { charge.updateWithdralFeeAmount(this.getAccountBalance()); UUID refNo = UUID.randomUUID(); - this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, appUser, backdatedTxnsAllowedTill, + this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, backdatedTxnsAllowedTill, refNo.toString()); } } @@ -3574,17 +3489,13 @@ public void escheat(AppUser appUser) { boolean postReversals = false; LocalDate transactionDate = DateUtils.getBusinessLocalDate(); if (this.getSummary().getAccountBalance(this.getCurrency()).isGreaterThanZero()) { - SavingsAccountTransaction transaction = SavingsAccountTransaction.escheat(this, transactionDate, appUser, postInterestAsOnDate); + SavingsAccountTransaction transaction = SavingsAccountTransaction.escheat(this, transactionDate, postInterestAsOnDate); this.transactions.add(transaction); } recalculateDailyBalances(Money.zero(this.currency), transactionDate, false, postReversals); this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); } - public void loadTransactions() { - transactions.size(); - } - public void loadLazyCollections() { transactions.size(); charges.size(); @@ -3822,7 +3733,7 @@ public LocalDate retrieveLastTransactionDate() { } LocalDate lastransactionDate = null; if (lastTransaction != null) { - lastransactionDate = lastTransaction.transactionLocalDate(); + lastransactionDate = lastTransaction.getTransactionDate(); } return lastransactionDate; } @@ -3835,7 +3746,7 @@ public LocalDate retrieveLastTransactionDateWithPivotConfig() { } LocalDate lastransactionDate = null; if (lastTransaction != null) { - lastransactionDate = lastTransaction.transactionLocalDate(); + lastransactionDate = lastTransaction.getTransactionDate(); } return lastransactionDate; } @@ -3904,10 +3815,6 @@ public BigDecimal getMinOverdraftForInterestCalculation() { return this.minOverdraftForInterestCalculation; } - public LocalDate getLockedInUntilDate() { - return this.lockedInUntilDate; - } - public Integer getDepositType() { return this.depositType; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java index b541a2d1d3b..0fd16e6dbba 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java @@ -56,7 +56,6 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; 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.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.organisation.staff.domain.Staff; import org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper; @@ -333,7 +332,7 @@ public SavingsAccount assembleFrom(final JsonCommand command, final AppUser subm nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax); account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper); - account.validateNewApplicationState(DateUtils.getBusinessLocalDate(), SAVINGS_ACCOUNT_RESOURCE_NAME); + account.validateNewApplicationState(SAVINGS_ACCOUNT_RESOURCE_NAME); account.validateAccountValuesWithProduct(); @@ -349,7 +348,7 @@ public SavingsAccount loadTransactionsToSavingsAccount(final SavingsAccount acco List savingsAccountTransactions = null; if (backdatedTxnsAllowedTill) { LocalDate pivotDate = account.getSummary().getInterestPostedTillDate(); - boolean isNotPresent = pivotDate == null ? true : false; + boolean isNotPresent = pivotDate == null; if (!isNotPresent) { // Get savings account transactions if (isRelaxingDaysConfigForPivotDateEnabled()) { @@ -468,7 +467,7 @@ public SavingsAccount assembleFrom(final Client client, final Group group, final product.withHoldTax()); account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper); - account.validateNewApplicationState(DateUtils.getBusinessLocalDate(), SAVINGS_ACCOUNT_RESOURCE_NAME); + account.validateNewApplicationState(SAVINGS_ACCOUNT_RESOURCE_NAME); account.validateAccountValuesWithProduct(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java index a426596eebd..8c525b20862 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountCharge.java @@ -41,7 +41,9 @@ import java.util.Map; import java.util.Objects; import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.organisation.monetary.domain.MoneyHelper; @@ -58,7 +60,7 @@ */ @Entity @Table(name = "m_savings_account_charge") -public class SavingsAccountCharge extends AbstractPersistableCustom { +public class SavingsAccountCharge extends AbstractAuditableWithUTCDateTimeCustom { private static final Logger LOG = LoggerFactory.getLogger(SavingsAccountCharge.class); @@ -448,7 +450,7 @@ public Map update(final JsonCommand command) { final String dateFormatAsInput = command.dateFormat(); final String localeAsInput = command.locale(); - if (command.isChangeInLocalDateParameterNamed(dueAsOfDateParamName, getDueLocalDate())) { + if (command.isChangeInLocalDateParameterNamed(dueAsOfDateParamName, getDueDate())) { final String valueAsInput = command.stringValueOfParameterNamed(dueAsOfDateParamName); actualChanges.put(dueAsOfDateParamName, valueAsInput); actualChanges.put(dateFormatParamName, dateFormatAsInput); @@ -521,7 +523,7 @@ private boolean isGreaterThanZero(final BigDecimal value) { return value.compareTo(BigDecimal.ZERO) > 0; } - public LocalDate getDueLocalDate() { + public LocalDate getDueDate() { return this.dueDate; } @@ -754,17 +756,13 @@ public boolean equals(Object o) { SavingsAccountCharge that = (SavingsAccountCharge) o; return (penaltyCharge == that.penaltyCharge) && (paid == that.paid) && (waived == that.waived) && (status == that.status) && Objects.equals(savingsAccount, that.savingsAccount) && Objects.equals(charge, that.charge) - && Objects.equals(chargeTime, that.chargeTime) && dueDate.compareTo(that.dueDate) == 0 - ? Boolean.TRUE - : Boolean.FALSE && Objects.equals(feeOnMonth, that.feeOnMonth) && Objects.equals(feeOnDay, that.feeOnDay) - && Objects.equals(feeInterval, that.feeInterval) - && Objects.equals(chargeCalculation, that.chargeCalculation) && Objects.equals(percentage, that.percentage) - && Objects.equals(amountPercentageAppliedTo, that.amountPercentageAppliedTo) - && Objects.equals(amount, that.amount) && Objects.equals(amountPaid, that.amountPaid) - && Objects.equals(amountWaived, that.amountWaived) - && Objects.equals(amountWrittenOff, that.amountWrittenOff) - && Objects.equals(amountOutstanding, that.amountOutstanding) - && inactivationDate.compareTo(that.inactivationDate) == 0 ? Boolean.TRUE : Boolean.FALSE; + && Objects.equals(chargeTime, that.chargeTime) && DateUtils.isEqual(dueDate, that.dueDate) + && Objects.equals(feeOnMonth, that.feeOnMonth) && Objects.equals(feeOnDay, that.feeOnDay) + && Objects.equals(feeInterval, that.feeInterval) && Objects.equals(chargeCalculation, that.chargeCalculation) + && Objects.equals(percentage, that.percentage) && Objects.equals(amountPercentageAppliedTo, that.amountPercentageAppliedTo) + && Objects.equals(amount, that.amount) && Objects.equals(amountPaid, that.amountPaid) + && Objects.equals(amountWaived, that.amountWaived) && Objects.equals(amountWrittenOff, that.amountWrittenOff) + && Objects.equals(amountOutstanding, that.amountOutstanding) && DateUtils.isEqual(inactivationDate, that.inactivationDate); } @Override @@ -803,12 +801,12 @@ public LocalDate getNextDueDateFrom(final LocalDate startingDate) { if (isAnnualFee() || isMonthlyFee()) { nextDueLocalDate = startingDate.withMonth(this.feeOnMonth); nextDueLocalDate = setDayOfMonth(nextDueLocalDate); - while (startingDate.isAfter(nextDueLocalDate)) { + while (DateUtils.isBefore(nextDueLocalDate, startingDate)) { nextDueLocalDate = calculateNextDueDate(nextDueLocalDate); } } else if (isWeeklyFee()) { - nextDueLocalDate = getDueLocalDate(); - while (startingDate.isAfter(nextDueLocalDate)) { + nextDueLocalDate = getDueDate(); + while (DateUtils.isBefore(nextDueLocalDate, startingDate)) { nextDueLocalDate = calculateNextDueDate(nextDueLocalDate); } } else { @@ -883,12 +881,11 @@ public boolean isRecurringFee() { } public boolean isChargeIsDue(final LocalDate nextDueDate) { - return this.getDueLocalDate().isBefore(nextDueDate); + return DateUtils.isBefore(getDueDate(), nextDueDate); } public boolean isChargeIsOverPaid(final LocalDate nextDueDate) { - final BigDecimal amountPaid = this.amountPaid == null ? BigDecimal.ZERO : amountPaid(); - return this.getDueLocalDate().isAfter(nextDueDate) && amountPaid.compareTo(BigDecimal.ZERO) > 0; + return DateUtils.isAfter(getDueDate(), nextDueDate) && MathUtil.isGreaterThanZero(amountPaid()); } private BigDecimal amountPaid() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java index 06f0db99581..81bece8b8e4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java @@ -25,7 +25,6 @@ import java.util.Set; import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail; import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues; -import org.apache.fineract.useradministration.domain.AppUser; public interface SavingsAccountDomainService { @@ -46,6 +45,5 @@ SavingsAccountTransaction handleDividendPayout(SavingsAccount account, LocalDate SavingsAccountTransaction handleReversal(SavingsAccount account, List savingsAccountTransactions, boolean backdatedTxnsAllowedTill); - SavingsAccountTransaction handleHold(SavingsAccount account, AppUser createdUser, BigDecimal amount, LocalDate transactionDate, - Boolean lienAllowed); + SavingsAccountTransaction handleHold(SavingsAccount account, BigDecimal amount, LocalDate transactionDate, Boolean lienAllowed); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java index f0457fea74b..ad8a8c175e3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java @@ -43,7 +43,6 @@ import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues; import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDTO; import org.apache.fineract.portfolio.savings.exception.DepositAccountTransactionNotAllowedException; -import org.apache.fineract.useradministration.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -83,8 +82,7 @@ public SavingsAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savi public SavingsAccountTransaction handleWithdrawal(final SavingsAccount account, final DateTimeFormatter fmt, final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final SavingsTransactionBooleanValues transactionBooleanValues, final boolean backdatedTxnsAllowedTill) { - - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); account.validateForAccountBlock(); account.validateForDebitBlock(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService @@ -107,7 +105,7 @@ public SavingsAccountTransaction handleWithdrawal(final SavingsAccount account, Integer accountType = null; final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, - paymentDetail, DateUtils.getLocalDateTimeOfSystem(), user, accountType); + paymentDetail, null, accountType); UUID refNo = UUID.randomUUID(); final SavingsAccountTransaction withdrawal = account.withdraw(transactionDTO, transactionBooleanValues.isApplyWithdrawFee(), backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate, refNo.toString()); @@ -147,14 +145,6 @@ public SavingsAccountTransaction handleWithdrawal(final SavingsAccount account, return withdrawal; } - private AppUser getAppUserIfPresent() { - AppUser user = null; - if (this.context != null) { - user = this.context.getAuthenticatedUserIfPresent(); - } - return user; - } - @Transactional @Override public SavingsAccountTransaction handleDeposit(final SavingsAccount account, final DateTimeFormatter fmt, @@ -169,7 +159,7 @@ private SavingsAccountTransaction handleDeposit(final SavingsAccount account, fi final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final boolean isAccountTransfer, final boolean isRegularTransaction, final SavingsAccountTransactionType savingsAccountTransactionType, final boolean backdatedTxnsAllowedTill) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); account.validateForAccountBlock(); account.validateForCreditBlock(); @@ -193,7 +183,7 @@ private SavingsAccountTransaction handleDeposit(final SavingsAccount account, fi Integer accountType = null; final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, - paymentDetail, DateUtils.getLocalDateTimeOfSystem(), user, accountType); + paymentDetail, null, accountType); UUID refNo = UUID.randomUUID(); final SavingsAccountTransaction deposit = account.deposit(transactionDTO, savingsAccountTransactionType, backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate, refNo.toString()); @@ -226,13 +216,10 @@ private SavingsAccountTransaction handleDeposit(final SavingsAccount account, fi @Transactional @Override - public SavingsAccountTransaction handleHold(final SavingsAccount account, final AppUser createdUser, BigDecimal amount, - LocalDate transactionDate, Boolean lienAllowed) { - final PaymentDetail paymentDetails = null; - - SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account, account.office(), paymentDetails, - transactionDate, Money.of(account.getCurrency(), amount), DateUtils.getLocalDateTimeOfSystem(), createdUser, lienAllowed); - return transaction; + public SavingsAccountTransaction handleHold(final SavingsAccount account, BigDecimal amount, LocalDate transactionDate, + Boolean lienAllowed) { + return SavingsAccountTransaction.holdAmount(account, account.office(), null, transactionDate, + Money.of(account.getCurrency(), amount), lienAllowed); } @Override @@ -322,7 +309,7 @@ public SavingsAccountTransaction handleReversal(SavingsAccount account, List updateRunningBalanceAndPivotDate(final boolean ba final SavingsAccountTransaction savingsAccountTransaction = savingsAccountTransactions.get(i); if (savingsAccountTransaction.isInterestPostingAndNotReversed() && !savingsAccountTransaction.isReversalTransaction() && !isUpdated) { - setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate()); + setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate()); isUpdated = true; if (!backdatedTxnsAllowedTill) { break; @@ -224,7 +224,7 @@ private HashMap updateRunningBalanceAndPivotDate(final boolean ba } if (savingsAccountTransaction.isOverdraftInterestAndNotReversed() && !savingsAccountTransaction.isReversalTransaction() && !isUpdated) { - setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate()); + setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate()); isUpdated = true; if (!backdatedTxnsAllowedTill) { break; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java index 2f33cbf4e67..6910fadcbd2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java @@ -18,6 +18,8 @@ */ package org.apache.fineract.portfolio.savings.domain; +import static org.apache.fineract.infrastructure.core.service.DateUtils.getSystemZoneId; + import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -29,14 +31,16 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; -import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; import org.apache.fineract.infrastructure.core.domain.LocalDateInterval; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; @@ -50,7 +54,6 @@ import org.apache.fineract.portfolio.savings.domain.interest.SavingsAccountTransactionDetailsForPostingPeriod; import org.apache.fineract.portfolio.savings.service.SavingsEnumerations; import org.apache.fineract.portfolio.tax.domain.TaxComponent; -import org.apache.fineract.useradministration.domain.AppUser; import org.springframework.util.CollectionUtils; /** @@ -58,7 +61,7 @@ */ @Entity @Table(name = "m_savings_account_transaction") -public final class SavingsAccountTransaction extends AbstractPersistableCustom { +public final class SavingsAccountTransaction extends AbstractAuditableWithUTCDateTimeCustom { @ManyToOne(optional = false) @JoinColumn(name = "savings_account_id", referencedColumnName = "id", nullable = false) @@ -102,16 +105,13 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { @Column(name = "overdraft_amount_derived", scale = 6, precision = 19, nullable = true) private BigDecimal overdraftAmount; - @Column(name = "created_date", nullable = false) - private LocalDateTime createdDate; + @Deprecated + @Column(name = "created_date", nullable = true) + private LocalDateTime createdDateToRemove; @Column(name = "submitted_on_date", nullable = false) private LocalDate submittedOnDate; - @ManyToOne - @JoinColumn(name = "appuser_id", nullable = true) - private AppUser appUser; - @Column(name = "is_manual", length = 1, nullable = true) private boolean isManualTransaction; @@ -143,16 +143,11 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { @Column(name = "ref_no", nullable = true) private String refNo; - SavingsAccountTransaction() { - this.dateOf = null; - this.typeOf = null; - this.createdDate = null; - } + SavingsAccountTransaction() {} private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, - final Integer typeOf, final LocalDate transactionLocalDate, final LocalDateTime createdDate, final BigDecimal amount, - final boolean isReversed, final AppUser appUser, final boolean isManualTransaction, final Boolean lienTransaction, - final String refNo) { + final Integer typeOf, final LocalDate transactionLocalDate, final BigDecimal amount, final boolean isReversed, + final boolean isManualTransaction, final Boolean lienTransaction, final String refNo) { this.savingsAccount = savingsAccount; this.office = office; this.typeOf = typeOf; @@ -160,42 +155,52 @@ private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Off this.amount = amount; this.reversed = isReversed; this.paymentDetail = paymentDetail; - this.createdDate = createdDate; + this.createdDateToRemove = null; // #audit backward compatibility deprecated this.submittedOnDate = DateUtils.getBusinessLocalDate(); - this.appUser = appUser; this.isManualTransaction = isManualTransaction; this.lienTransaction = lienTransaction; this.refNo = refNo; } + private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf, + final LocalDate transactionLocalDate, final Money amount, final boolean isReversed, final boolean isManualTransaction, + final Boolean lienTransaction, final String refNo) { + this(savingsAccount, office, null, typeOf, transactionLocalDate, amount, isReversed, isManualTransaction, lienTransaction, refNo); + } + + private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, + final Integer typeOf, final LocalDate transactionLocalDate, final Money amount, final boolean isReversed, + final boolean isManualTransaction, final Boolean lienTransaction, final String refNo) { + this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate, amount.getAmount(), isReversed, isManualTransaction, + lienTransaction, refNo); + } + public static SavingsAccountTransaction deposit(final SavingsAccount savingsAccount, final Office office, - final PaymentDetail paymentDetail, final LocalDate date, final Money amount, LocalDateTime createdDate, final AppUser appUser, - final String refNo) { + final PaymentDetail paymentDetail, final LocalDate date, final Money amount, final String refNo) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.DEPOSIT.getValue(), date, - createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction, refNo); + amount, isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction deposit(final SavingsAccount savingsAccount, final Office office, - final PaymentDetail paymentDetail, final LocalDate date, final Money amount, LocalDateTime createdDate, final AppUser appUser, + final PaymentDetail paymentDetail, final LocalDate date, final Money amount, final SavingsAccountTransactionType savingsAccountTransactionType, final String refNo) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; - return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, savingsAccountTransactionType.getValue(), date, - createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction, refNo); + return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, savingsAccountTransactionType.getValue(), date, amount, + isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction withdrawal(final SavingsAccount savingsAccount, final Office office, - final PaymentDetail paymentDetail, final LocalDate date, final Money amount, LocalDateTime createdDate, final AppUser appUser, - final String refNo) { + final PaymentDetail paymentDetail, final LocalDate date, final Money amount, final String refNo) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.WITHDRAWAL.getValue(), - date, createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction, refNo); + date, amount, isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction interestPosting(final SavingsAccount savingsAccount, final Office office, final LocalDate date, @@ -204,7 +209,7 @@ public static SavingsAccountTransaction interestPosting(final SavingsAccount sav final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.INTEREST_POSTING.getValue(), date, - amount, isReversed, null, isManualTransaction, lienTransaction, refNo); + amount, isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction overdraftInterest(final SavingsAccount savingsAccount, final Office office, @@ -213,82 +218,82 @@ public static SavingsAccountTransaction overdraftInterest(final SavingsAccount s final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue(), date, - amount, isReversed, null, isManualTransaction, lienTransaction, refNo); + amount, isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction withdrawalFee(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final Money amount, final AppUser appUser, final String refNo) { + final Money amount, final String refNo) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue(), date, amount, - isReversed, appUser, isManualTransaction, lienTransaction, refNo); + isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction annualFee(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final Money amount, final AppUser appUser) { + final Money amount) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.ANNUAL_FEE.getValue(), date, amount, - isReversed, appUser, isManualTransaction, lienTransaction, refNo); + isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction charge(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final Money amount, final AppUser appUser) { + final Money amount) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.PAY_CHARGE.getValue(), date, amount, - isReversed, appUser, isManualTransaction, lienTransaction, refNo); + isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction waiver(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final Money amount, final AppUser appUser) { + final Money amount) { final boolean isReversed = false; final boolean isManualTransaction = false; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.WAIVE_CHARGES.getValue(), date, amount, - isReversed, appUser, isManualTransaction, lienTransaction, refNo); + isReversed, isManualTransaction, lienTransaction, refNo); } - public static SavingsAccountTransaction initiateTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final AppUser appUser) { + public static SavingsAccountTransaction initiateTransfer(final SavingsAccount savingsAccount, final Office office, + final LocalDate date) { final boolean isReversed = false; final boolean isManualTransaction = false; final PaymentDetail paymentDetail = null; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, - SavingsAccountTransactionType.INITIATE_TRANSFER.getValue(), date, DateUtils.getLocalDateTimeOfSystem(), - savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction, lienTransaction, refNo); + SavingsAccountTransactionType.INITIATE_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), + isReversed, isManualTransaction, lienTransaction, refNo); } - public static SavingsAccountTransaction approveTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final AppUser appUser) { + public static SavingsAccountTransaction approveTransfer(final SavingsAccount savingsAccount, final Office office, + final LocalDate date) { final boolean isReversed = false; final boolean isManualTransaction = false; final PaymentDetail paymentDetail = null; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, - SavingsAccountTransactionType.APPROVE_TRANSFER.getValue(), date, DateUtils.getLocalDateTimeOfSystem(), - savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction, lienTransaction, refNo); + SavingsAccountTransactionType.APPROVE_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), + isReversed, isManualTransaction, lienTransaction, refNo); } - public static SavingsAccountTransaction withdrawTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date, - final AppUser appUser) { + public static SavingsAccountTransaction withdrawTransfer(final SavingsAccount savingsAccount, final Office office, + final LocalDate date) { final boolean isReversed = false; final boolean isManualTransaction = false; final PaymentDetail paymentDetail = null; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, - SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date, DateUtils.getLocalDateTimeOfSystem(), - savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, isManualTransaction, lienTransaction, refNo); + SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), + isReversed, isManualTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction withHoldTax(final SavingsAccount savingsAccount, final Office office, final LocalDate date, @@ -298,70 +303,42 @@ public static SavingsAccountTransaction withHoldTax(final SavingsAccount savings final Boolean lienTransaction = false; final String refNo = null; SavingsAccountTransaction accountTransaction = new SavingsAccountTransaction(savingsAccount, office, - SavingsAccountTransactionType.WITHHOLD_TAX.getValue(), date, amount, isReversed, null, isManualTransaction, lienTransaction, + SavingsAccountTransactionType.WITHHOLD_TAX.getValue(), date, amount, isReversed, isManualTransaction, lienTransaction, refNo); updateTaxDetails(taxDetails, accountTransaction); return accountTransaction; } - public static SavingsAccountTransaction escheat(final SavingsAccount savingsAccount, final LocalDate date, final AppUser appUser, + public static SavingsAccountTransaction escheat(final SavingsAccount savingsAccount, final LocalDate date, final boolean accountTransaction) { final boolean isReversed = false; final PaymentDetail paymentDetail = null; final Boolean lienTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, savingsAccount.office(), paymentDetail, - SavingsAccountTransactionType.ESCHEAT.getValue(), date, DateUtils.getLocalDateTimeOfSystem(), - savingsAccount.getSummary().getAccountBalance(), isReversed, appUser, accountTransaction, lienTransaction, refNo); - } - - public static void updateTaxDetails(final Map taxDetails, - final SavingsAccountTransaction accountTransaction) { - if (taxDetails != null) { - for (Map.Entry mapEntry : taxDetails.entrySet()) { - accountTransaction.getTaxDetails() - .add(new SavingsAccountTransactionTaxDetails(accountTransaction, mapEntry.getKey(), mapEntry.getValue())); - } - } + SavingsAccountTransactionType.ESCHEAT.getValue(), date, savingsAccount.getSummary().getAccountBalance(), isReversed, + accountTransaction, lienTransaction, refNo); } public static SavingsAccountTransaction copyTransaction(SavingsAccountTransaction accountTransaction) { return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail, - accountTransaction.typeOf, accountTransaction.transactionLocalDate(), DateUtils.getLocalDateTimeOfSystem(), - accountTransaction.amount, accountTransaction.reversed, accountTransaction.appUser, accountTransaction.isManualTransaction, - accountTransaction.lienTransaction, accountTransaction.refNo); - } - - private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf, - final LocalDate transactionLocalDate, final Money amount, final boolean isReversed, final AppUser appUser, - final boolean isManualTransaction, final Boolean lienTransaction, final String refNo) { - this(savingsAccount, office, null, typeOf, transactionLocalDate, DateUtils.getLocalDateTimeOfSystem(), amount, isReversed, appUser, - isManualTransaction, lienTransaction, refNo); - } - - private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, - final Integer typeOf, final LocalDate transactionLocalDate, final LocalDateTime createdDate, final Money amount, - final boolean isReversed, final AppUser appUser, final boolean isManualTransaction, final Boolean lienTransaction, - final String refNo) { - this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate, createdDate, amount.getAmount(), isReversed, appUser, - isManualTransaction, lienTransaction, refNo); + accountTransaction.typeOf, accountTransaction.getTransactionDate(), accountTransaction.amount, accountTransaction.reversed, + accountTransaction.isManualTransaction, accountTransaction.lienTransaction, accountTransaction.refNo); } public static SavingsAccountTransaction holdAmount(final SavingsAccount savingsAccount, final Office office, - final PaymentDetail paymentDetail, final LocalDate date, final Money amount, LocalDateTime createdDate, final AppUser appUser, - final Boolean lienTransaction) { + final PaymentDetail paymentDetail, final LocalDate date, final Money amount, final Boolean lienTransaction) { final boolean isReversed = false; final boolean isManualTransaction = false; final String refNo = null; return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.AMOUNT_HOLD.getValue(), - date, createdDate, amount, isReversed, appUser, isManualTransaction, lienTransaction, refNo); + date, amount, isReversed, isManualTransaction, lienTransaction, refNo); } - public static SavingsAccountTransaction releaseAmount(SavingsAccountTransaction accountTransaction, LocalDate transactionDate, - LocalDateTime createdDate, final AppUser appUser) { + public static SavingsAccountTransaction releaseAmount(SavingsAccountTransaction accountTransaction, LocalDate transactionDate) { return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail, - SavingsAccountTransactionType.AMOUNT_RELEASE.getValue(), transactionDate, createdDate, accountTransaction.amount, - accountTransaction.reversed, appUser, accountTransaction.isManualTransaction, accountTransaction.lienTransaction, + SavingsAccountTransactionType.AMOUNT_RELEASE.getValue(), transactionDate, accountTransaction.amount, + accountTransaction.reversed, accountTransaction.isManualTransaction, accountTransaction.lienTransaction, accountTransaction.refNo); } @@ -371,25 +348,154 @@ public static SavingsAccountTransaction reversal(SavingsAccountTransaction accou sat.setReversalTransaction(true); sat.originalTxnId = accountTransaction.getId(); return sat; + } + + public static void updateTaxDetails(final Map taxDetails, + final SavingsAccountTransaction accountTransaction) { + if (taxDetails != null) { + for (Map.Entry mapEntry : taxDetails.entrySet()) { + accountTransaction.getTaxDetails() + .add(new SavingsAccountTransactionTaxDetails(accountTransaction, mapEntry.getKey(), mapEntry.getValue())); + } + } + } + public SavingsAccount getSavingsAccount() { + return this.savingsAccount; } - public LocalDate transactionLocalDate() { + public LocalDate getTransactionDate() { return this.dateOf; } + public LocalDate getEndOfBalanceDate() { + return balanceEndDate; + } + + public boolean isReversed() { + return this.reversed; + } + public void reverse() { this.reversed = true; } + public BigDecimal getAmount() { + return this.amount; + } + public Money getAmount(final MonetaryCurrency currency) { return Money.of(currency, this.amount); } + public void setAmount(final Money amount) { + this.amount = amount == null ? null : amount.getAmount(); + } + + public BigDecimal getRunningBalance() { + return this.runningBalance; + } + public Money getRunningBalance(final MonetaryCurrency currency) { return Money.of(currency, this.runningBalance); } + public void setRunningBalance(Money balance) { + this.runningBalance = balance == null ? null : balance.getAmount(); + } + + public boolean isManualTransaction() { + return this.isManualTransaction; + } + + public Set getSavingsAccountChargesPaid() { + return this.savingsAccountChargesPaid; + } + + public BigDecimal getOverdraftAmount() { + return this.overdraftAmount; + } + + public Money getOverdraftAmount(final MonetaryCurrency currency) { + return Money.of(currency, this.overdraftAmount); + } + + void setOverdraftAmount(Money overdraftAmount) { + this.overdraftAmount = overdraftAmount == null ? null : overdraftAmount.getAmount(); + } + + public List getTaxDetails() { + return this.taxDetails; + } + + public List getNotes() { + return notes; + } + + public Integer getTypeOf() { + return this.typeOf; + } + + public SavingsAccountTransactionType getTransactionType() { + return SavingsAccountTransactionType.fromInt(this.typeOf); + } + + public LocalDate getDateOf() { + return this.dateOf; + } + + public String getRefNo() { + return this.refNo; + } + + public PaymentDetail getPaymentDetail() { + return this.paymentDetail; + } + + public void updateReleaseId(Long releaseId) { + this.releaseIdOfHoldAmountTransaction = releaseId; + } + + public void updateReason(String reasonForBlock) { + this.reasonForBlock = reasonForBlock; + } + + public Long getReleaseIdOfHoldAmountTransaction() { + return this.releaseIdOfHoldAmountTransaction; + } + + public MonetaryCurrency getCurrency() { + return savingsAccount == null ? null : savingsAccount.getCurrency(); + } + + public Long getOfficeId() { + return this.office.getId(); + } + + public LocalDate getBalanceEndDate() { + return this.balanceEndDate; + } + + public BigDecimal getCumulativeBalance() { + return this.cumulativeBalance; + } + + public Integer getBalanceNumberOfDays() { + return this.balanceNumberOfDays; + } + + public LocalDate getSubmittedOnDate() { + return submittedOnDate; + } + + public boolean isReversalTransaction() { + return reversalTransaction; + } + + void setReversalTransaction(boolean reversalTransaction) { + this.reversalTransaction = reversalTransaction; + } + public boolean isDeposit() { return getTransactionType().isDeposit(); } @@ -442,10 +548,6 @@ public boolean isNotReversed() { return !isReversed(); } - public boolean isReversed() { - return this.reversed; - } - public boolean isTransferInitiation() { return getTransactionType().isTransferInitiation(); } @@ -466,14 +568,6 @@ public boolean isTransferRelatedTransaction() { return isTransferInitiation() || isTransferApproval() || isTransferRejection() || isTransferWithdrawal(); } - public boolean occursOn(final LocalDate occursOnDate) { - return getTransactionLocalDate().isEqual(occursOnDate); - } - - public void setLoanDisbursement(boolean isLoanDisbursement) { - this.isLoanDisbursement = isLoanDisbursement; - } - public void zeroBalanceFields() { this.runningBalance = null; this.cumulativeBalance = null; @@ -481,35 +575,19 @@ public void zeroBalanceFields() { this.balanceNumberOfDays = null; } - public void updateRunningBalance(final Money balance) { - this.runningBalance = balance.getAmount(); - } - public void updateCumulativeBalanceAndDates(final MonetaryCurrency currency, final LocalDate endOfBalanceDate) { // balance end date should not be before transaction date - if (endOfBalanceDate != null && endOfBalanceDate.isBefore(this.transactionLocalDate())) { - this.balanceEndDate = this.transactionLocalDate(); + if (endOfBalanceDate != null && DateUtils.isBefore(endOfBalanceDate, this.getTransactionDate())) { + this.balanceEndDate = this.getTransactionDate(); } else { this.balanceEndDate = endOfBalanceDate; } - this.balanceNumberOfDays = LocalDateInterval.create(getTransactionLocalDate(), endOfBalanceDate).daysInPeriodInclusiveOfEndDate(); + this.balanceNumberOfDays = LocalDateInterval.create(getTransactionDate(), endOfBalanceDate).daysInPeriodInclusiveOfEndDate(); this.cumulativeBalance = Money.of(currency, this.runningBalance).multipliedBy(this.balanceNumberOfDays).getAmount(); } - public LocalDate getTransactionLocalDate() { - return this.dateOf; - } - - public LocalDate getLastTransactionDate() { - return this.dateOf; - } - - public LocalDate getEndOfBalanceLocalDate() { - return balanceEndDate; - } - public boolean isAcceptableForDailyBalance(final LocalDateInterval interestPeriodInterval) { - return isNotReversed() && interestPeriodInterval.contains(getTransactionLocalDate()) && isABalanceForAtLeastOneDay(); + return isNotReversed() && interestPeriodInterval.contains(getTransactionDate()) && isABalanceForAtLeastOneDay(); } private boolean isABalanceForAtLeastOneDay() { @@ -530,7 +608,7 @@ public Map toMapData(final String currencyCode) { thisTransactionData.put("officeId", this.office.getId()); thisTransactionData.put("type", transactionType); thisTransactionData.put("reversed", isReversed()); - thisTransactionData.put("date", getTransactionLocalDate()); + thisTransactionData.put("date", getTransactionDate()); thisTransactionData.put("currencyCode", currencyCode); thisTransactionData.put("amount", this.amount); thisTransactionData.put("overdraftAmount", this.overdraftAmount); @@ -573,29 +651,28 @@ public Map toMapData(final String currencyCode) { return thisTransactionData; } - public boolean isAfter(final LocalDate transactionDate) { - return getTransactionLocalDate().isAfter(transactionDate); + public boolean isBefore(final LocalDate date) { + return DateUtils.isBefore(getTransactionDate(), date); } - public boolean isManualTransaction() { - return this.isManualTransaction; + public boolean isAfter(final LocalDate date) { + return DateUtils.isAfter(getTransactionDate(), date); } - public void setPostInterestAsOn(boolean isManualTransaction) { - this.isManualTransaction = isManualTransaction; + public boolean occursOn(final LocalDate date) { + return DateUtils.isEqual(getTransactionDate(), date); } public EndOfDayBalance toEndOfDayBalance(final LocalDateInterval periodInterval, final MonetaryCurrency currency) { - final Money endOfDayBalance = Money.of(currency, this.runningBalance); final Money openingBalance = endOfDayBalance; LocalDate balanceDate = periodInterval.startDate(); int numberOfDays = periodInterval.daysInPeriodInclusiveOfEndDate(); - if (periodInterval.contains(getTransactionLocalDate())) { - balanceDate = getTransactionLocalDate(); - final LocalDateInterval newInterval = LocalDateInterval.create(getTransactionLocalDate(), periodInterval.endDate()); + if (periodInterval.contains(getTransactionDate())) { + balanceDate = getTransactionDate(); + final LocalDateInterval newInterval = LocalDateInterval.create(getTransactionDate(), periodInterval.endDate()); numberOfDays = newInterval.daysInPeriodInclusiveOfEndDate(); } @@ -603,7 +680,6 @@ public EndOfDayBalance toEndOfDayBalance(final LocalDateInterval periodInterval, } public EndOfDayBalance toEndOfDayBalance(final Money openingBalance, final LocalDate nextTransactionDate) { - final MonetaryCurrency currency = openingBalance.getCurrency(); Money endOfDayBalance = openingBalance.copy(); if (isDeposit() || isDividendPayoutAndNotReversed()) { @@ -612,11 +688,11 @@ public EndOfDayBalance toEndOfDayBalance(final Money openingBalance, final Local endOfDayBalance = openingBalance.minus(getAmount(currency)); } - int numberOfDays = LocalDateInterval.create(getTransactionLocalDate(), nextTransactionDate).daysInPeriodInclusiveOfEndDate(); + int numberOfDays = LocalDateInterval.create(getTransactionDate(), nextTransactionDate).daysInPeriodInclusiveOfEndDate(); if (!openingBalance.isEqualTo(endOfDayBalance) && numberOfDays > 1) { numberOfDays = numberOfDays - 1; } - return EndOfDayBalance.from(getTransactionLocalDate(), openingBalance, endOfDayBalance, numberOfDays); + return EndOfDayBalance.from(getTransactionDate(), openingBalance, endOfDayBalance, numberOfDays); } public EndOfDayBalance toEndOfDayBalance(final Money openingBalance) { @@ -629,24 +705,23 @@ public EndOfDayBalance toEndOfDayBalance(final Money openingBalance) { if (openingBalance.isGreaterThanZero() || this.savingsAccount.allowOverdraft()) { endOfDayBalance = openingBalance.minus(getAmount(currency)); } else { - endOfDayBalance = Money.of(currency, this.runningBalance); + endOfDayBalance = getRunningBalance(currency); } } - return EndOfDayBalance.from(getTransactionLocalDate(), openingBalance, endOfDayBalance, this.balanceNumberOfDays); + return EndOfDayBalance.from(getTransactionDate(), openingBalance, endOfDayBalance, this.balanceNumberOfDays); } public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy) { - final MonetaryCurrency currency = openingBalance.getCurrency(); Money endOfDayBalance = openingBalance.copy(); int numberOfDaysOfBalance = this.balanceNumberOfDays; - LocalDate balanceStartDate = getTransactionLocalDate(); - LocalDate balanceEndDate = getEndOfBalanceLocalDate(); + LocalDate balanceStartDate = getTransactionDate(); + LocalDate balanceEndDate = getEndOfBalanceDate(); - if (boundedBy.startDate().isAfter(balanceStartDate)) { + if (DateUtils.isBefore(balanceStartDate, boundedBy.startDate())) { balanceStartDate = boundedBy.startDate(); final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -661,12 +736,12 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi if (endOfDayBalance.isGreaterThanZero() || this.savingsAccount.allowOverdraft()) { endOfDayBalance = endOfDayBalance.minus(getAmount(currency)); } else { - endOfDayBalance = Money.of(currency, this.runningBalance); + endOfDayBalance = getRunningBalance(currency); } } } - if (balanceEndDate.isAfter(boundedBy.endDate())) { + if (DateUtils.isAfter(balanceEndDate, boundedBy.endDate())) { balanceEndDate = boundedBy.endDate(); final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); @@ -676,16 +751,16 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi } public boolean isBalanceInExistencesForOneDayOrMore() { - return this.balanceNumberOfDays != null && this.balanceNumberOfDays.intValue() >= 1; + return this.balanceNumberOfDays != null && this.balanceNumberOfDays >= 1; } public boolean fallsWithin(final LocalDateInterval periodInterval) { - final LocalDateInterval balanceInterval = LocalDateInterval.create(getTransactionLocalDate(), getEndOfBalanceLocalDate()); + final LocalDateInterval balanceInterval = LocalDateInterval.create(getTransactionDate(), getEndOfBalanceDate()); return periodInterval.contains(balanceInterval); } public boolean spansAnyPortionOf(final LocalDateInterval periodInterval) { - final LocalDateInterval balanceInterval = LocalDateInterval.create(getTransactionLocalDate(), getEndOfBalanceLocalDate()); + final LocalDateInterval balanceInterval = LocalDateInterval.create(getTransactionDate(), getEndOfBalanceDate()); return balanceInterval.containsPortionOf(periodInterval); } @@ -793,123 +868,22 @@ private SavingsAccountChargePaidBy getSavingsAccountChargePaidBy() { return null; } - public Set getSavingsAccountChargesPaid() { - return this.savingsAccountChargesPaid; - } - - public void updateOverdraftAmount(BigDecimal overdraftAmount) { - this.overdraftAmount = overdraftAmount; - } - - public Money getOverdraftAmount(final MonetaryCurrency currency) { - return Money.of(currency, this.overdraftAmount); - } - public boolean isPaymentForCurrentCharge(final SavingsAccountCharge savingsAccountCharge) { final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); return chargePaidBy != null && chargePaidBy.getSavingsAccountCharge().equals(savingsAccountCharge); } - public BigDecimal getAmount() { - return this.amount; - } - - public List getTaxDetails() { - return this.taxDetails; - } - - public List getNotes() { - return notes; - } - - public void updateAmount(final Money amount) { - this.amount = amount.getAmount(); - } - - public Integer getTypeOf() { - return this.typeOf; - } - - public SavingsAccountTransactionType getTransactionType() { - return SavingsAccountTransactionType.fromInt(this.typeOf); - } - - public SavingsAccount getSavingsAccount() { - return this.savingsAccount; - } - - public void setSavingsAccount(SavingsAccount savingsAccount) { - this.savingsAccount = savingsAccount; - } - - public LocalDate getDateOf() { - return this.dateOf; - } - - public String getRefNo() { - return this.refNo; - } - - public PaymentDetail getPaymentDetail() { - return this.paymentDetail; - } - - public void updateReleaseId(Long releaseId) { - this.releaseIdOfHoldAmountTransaction = releaseId; - } - - public void updateReason(String reasonForBlock) { - this.reasonForBlock = reasonForBlock; - } - - public Long getReleaseIdOfHoldAmountTransaction() { - return this.releaseIdOfHoldAmountTransaction; + @Override + public Optional getCreatedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getCreatedDate() + .orElse(createdDateToRemove == null ? null : createdDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); } public boolean isAmountOnHoldNotReleased() { return (isAmountOnHold() && getReleaseIdOfHoldAmountTransaction() == null); } - public Long getOfficeId() { - return this.office.getId(); - } - - public LocalDate getBalanceEndDate() { - return this.balanceEndDate; - } - - public BigDecimal getCumulativeBalance() { - return this.cumulativeBalance; - } - - public Integer getBalanceNumberOfDays() { - return this.balanceNumberOfDays; - } - - public Long getAppUserId() { - return this.appUser.getId(); - } - - public LocalDateTime getCreatedDate() { - return this.createdDate; - } - - public LocalDate getSubmittedOnDate() { - return submittedOnDate; - } - - public boolean getIsManualTransaction() { - return this.isManualTransaction; - } - - public void setReversalTransaction(boolean reversalTransaction) { - this.reversalTransaction = reversalTransaction; - } - - public boolean isReversalTransaction() { - return reversalTransaction; - } - public SavingsAccountTransactionDetailsForPostingPeriod toSavingsAccountTransactionDetailsForPostingPeriod(MonetaryCurrency currency, boolean isAllowOverDraft) { return new SavingsAccountTransactionDetailsForPostingPeriod(getId(), this.dateOf, this.balanceEndDate, this.runningBalance, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionComparator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionComparator.java index 3527db7fe38..d526246c573 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionComparator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionComparator.java @@ -19,6 +19,7 @@ package org.apache.fineract.portfolio.savings.domain; import java.util.Comparator; +import org.apache.fineract.infrastructure.core.service.DateUtils; /** * Sort savings account transactions by transaction date and transaction type placing @@ -27,18 +28,17 @@ public class SavingsAccountTransactionComparator implements Comparator { @Override public int compare(final SavingsAccountTransactionData o1, final SavingsAccountTransactionData o2) { - int compareResult = 0; - - final int comparsion = o1.getTransactionDate().compareTo(o2.getTransactionDate()); - if (comparsion == 0) { - compareResult = o1.getSubmittedOnDate().compareTo(o2.getSubmittedOnDate()); - if (compareResult == 0 && o1.getId() != null && o2.getId() != null) { - compareResult = o1.getId().compareTo(o2.getId()); - } else { - compareResult = comparsion; - } - } else { - compareResult = comparsion; + int result = DateUtils.compare(o1.getTransactionDate(), o2.getTransactionDate()); + if (result != 0) { + return result; + } + result = DateUtils.compare(o1.getSubmittedOnDate(), o2.getSubmittedOnDate()); + if (result != 0) { + return result; + } + if (o1.getId() != null && o2.getId() != null) { + return o1.getId().compareTo(o2.getId()); } - return compareResult; + return 0; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsOfficerAssignmentHistory.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsOfficerAssignmentHistory.java index 995bd3d521a..6060339d9fb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsOfficerAssignmentHistory.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsOfficerAssignmentHistory.java @@ -18,18 +18,24 @@ */ package org.apache.fineract.portfolio.savings.domain; +import static org.apache.fineract.infrastructure.core.service.DateUtils.getSystemZoneId; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.time.LocalDate; -import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.Optional; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.staff.domain.Staff; @Entity @Table(name = "m_savings_officer_assignment_history") -public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom { +public class SavingsOfficerAssignmentHistory extends AbstractAuditableWithUTCDateTimeCustom { @ManyToOne @JoinColumn(name = "account_id", nullable = false) @@ -45,10 +51,13 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom { @Column(name = "end_date") private LocalDate endDate; - public static SavingsOfficerAssignmentHistory createNew(final SavingsAccount account, final Staff savingsOfficer, - final LocalDate assignmentDate) { - return new SavingsOfficerAssignmentHistory(account, savingsOfficer, assignmentDate, null); - } + @Deprecated + @Column(name = "created_date") + private LocalDateTime createdDateToRemove; + + @Deprecated + @Column(name = "lastmodified_date") + private LocalDateTime lastModifiedDateToRemove; protected SavingsOfficerAssignmentHistory() { // @@ -62,7 +71,12 @@ private SavingsOfficerAssignmentHistory(final SavingsAccount account, final Staf this.endDate = endDate; } - public void updateSavingsOfficer(final Staff savingsOfficer) { + public static SavingsOfficerAssignmentHistory createNew(final SavingsAccount account, final Staff savingsOfficer, + final LocalDate startDate) { + return new SavingsOfficerAssignmentHistory(account, savingsOfficer, startDate, null); + } + + public void setSavingsOfficer(final Staff savingsOfficer) { this.savingsOfficer = savingsOfficer; } @@ -70,28 +84,28 @@ public boolean isSameSavingsOfficer(final Staff staff) { return this.savingsOfficer.identifiedBy(staff); } - public void updateStartDate(final LocalDate startDate) { - this.startDate = startDate; + public LocalDate getStartDate() { + return this.startDate; } - public void updateEndDate(final LocalDate endDate) { - this.endDate = endDate; + public void setStartDate(final LocalDate startDate) { + this.startDate = startDate; } - public boolean matchesStartDateOf(final LocalDate matchingDate) { - return getStartDate().isEqual(matchingDate); + public LocalDate getEndDate() { + return this.endDate; } - public LocalDate getStartDate() { - return this.startDate; + public void setEndDate(final LocalDate endDate) { + this.endDate = endDate; } - public boolean hasStartDateBefore(final LocalDate matchingDate) { - return matchingDate.isBefore(getStartDate()); + public boolean matchesStartDateOf(final LocalDate matchingDate) { + return DateUtils.isEqual(matchingDate, getStartDate()); } - public boolean isCurrentRecord() { - return this.endDate == null; + public boolean isBeforeStartDate(final LocalDate matchingDate) { + return DateUtils.isBefore(matchingDate, getStartDate()); } /** @@ -100,12 +114,25 @@ public boolean isCurrentRecord() { * @param compareDate * @return */ - public boolean isEndDateAfter(final LocalDate compareDate) { - return this.endDate != null && this.endDate.isAfter(compareDate); + public boolean isBeforeEndDate(final LocalDate compareDate) { + return DateUtils.isBefore(compareDate, this.endDate); } - public LocalDate getEndDate() { - return this.endDate; + public boolean isCurrentRecord() { + return this.endDate == null; } + @Override + public Optional getCreatedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getCreatedDate() + .orElse(createdDateToRemove == null ? null : createdDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); + } + + @Override + public Optional getLastModifiedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getLastModifiedDate() + .orElse(lastModifiedDateToRemove == null ? null : lastModifiedDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleConfig.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleConfig.java index d32db1c09e6..64cc452ce31 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleConfig.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleConfig.java @@ -20,6 +20,7 @@ import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory; import org.apache.fineract.infrastructure.jobs.service.JobName; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; @@ -43,6 +44,8 @@ public class GenerateRdScheduleConfig { private RoutingDataSourceServiceFactory dataSourceServiceFactory; @Autowired private DepositAccountReadPlatformService depositAccountReadPlatformService; + @Autowired + private PlatformSecurityContext securityContext; @Bean protected Step generateRdScheduleStep() { @@ -58,6 +61,6 @@ public Job generateRdScheduleJob() { @Bean public GenerateRdScheduleTasklet generateRdScheduleTasklet() { - return new GenerateRdScheduleTasklet(dataSourceServiceFactory, depositAccountReadPlatformService); + return new GenerateRdScheduleTasklet(dataSourceServiceFactory, depositAccountReadPlatformService, securityContext); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleTasklet.java index a555afd0466..e49ffe3ce5e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/jobs/generaterdschedule/GenerateRdScheduleTasklet.java @@ -18,15 +18,23 @@ */ package org.apache.fineract.portfolio.savings.jobs.generaterdschedule; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_BY_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE_DB_FIELD; + import java.math.BigDecimal; import java.time.LocalDate; -import java.time.format.DateTimeFormatter; +import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.portfolio.savings.DepositAccountUtils; import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService; import org.springframework.batch.core.StepContribution; @@ -41,19 +49,20 @@ public class GenerateRdScheduleTasklet implements Tasklet { private final RoutingDataSourceServiceFactory dataSourceServiceFactory; private final DepositAccountReadPlatformService depositAccountReadPlatformService; - private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private final DateTimeFormatter formatterWithTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + private final PlatformSecurityContext securityContext; @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource()); final Collection> scheduleDetails = depositAccountReadPlatformService.retriveDataForRDScheduleCreation(); - String insertSql = "INSERT INTO m_mandatory_savings_schedule (savings_account_id, duedate, installment, deposit_amount, completed_derived, created_date, lastmodified_date) VALUES "; - StringBuilder sb = new StringBuilder(); - String currentDate = DateUtils.getLocalDateTimeOfTenant().format(DateUtils.DEFAULT_DATETIME_FORMATTER); + String insertSql = "INSERT INTO m_mandatory_savings_schedule (savings_account_id, duedate, installment, deposit_amount, completed_derived, " + + CREATED_DATE_DB_FIELD + ", " + CREATED_BY_DB_FIELD + ", " + LAST_MODIFIED_DATE_DB_FIELD + ", " + LAST_MODIFIED_BY_DB_FIELD + + ") " + "VALUES (?, ?, ?, ?, ?, ?, ?)"; + List params = new ArrayList<>(); + Long userId = securityContext.authenticatedUser().getId(); int iterations = 0; for (Map details : scheduleDetails) { - Long count = (Long) details.get("futureInstallemts"); + Long count = (Long) details.get("futureInstallments"); if (count == null) { count = 0L; } @@ -66,34 +75,20 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon count++; installmentNumber++; lastDepositDate = DepositAccountUtils.calculateNextDepositDate(lastDepositDate, recurrence); - - if (sb.length() > 0) { - sb.append(", "); - } - sb.append("("); - sb.append(savingsId); - sb.append(",'"); - sb.append(formatter.format(lastDepositDate)); - sb.append("',"); - sb.append(installmentNumber); - sb.append(","); - sb.append(amount); - sb.append(", b'0','"); - sb.append(currentDate); - sb.append("','"); - sb.append(currentDate); - sb.append("')"); + OffsetDateTime auditTime = DateUtils.getAuditOffsetDateTime(); + params.add(new Object[] { savingsId, lastDepositDate, installmentNumber, amount, false, auditTime, userId, auditTime, + userId }); iterations++; - if (iterations > 200) { - jdbcTemplate.update(insertSql + sb); // NOSONAR - sb = new StringBuilder(); - } - + } + if (iterations > 200) { + jdbcTemplate.batchUpdate(insertSql, params); + params.clear(); + iterations = 0; } } - if (sb.length() > 0) { - jdbcTemplate.update(insertSql + sb); // NOSONAR + if (!params.isEmpty()) { + jdbcTemplate.batchUpdate(insertSql, params); } return RepeatStatus.FINISHED; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java index c9698b5ad15..6935606854a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java @@ -18,6 +18,8 @@ */ package org.apache.fineract.portfolio.savings.service; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY_DB_FIELD; + import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; @@ -524,7 +526,7 @@ public Collection> retriveDataForRDScheduleCreation() { sb.append(" select rd.savings_account_id savingsId, rd.mandatory_recommended_deposit_amount as amount,"); sb.append(" mc.recurrence as recurrence ,"); sb.append(" max(ms.duedate) as dueDate , max(ms.installment) as installment,"); - sb.append(" count(ms.installment) as futureInstallemts"); + sb.append(" count(ms.installment) as futureInstallments"); sb.append(" from m_deposit_account_term_and_preclosure dat "); sb.append(" inner join m_savings_account sa on sa.id = dat.savings_account_id and sa.status_enum = ?"); sb.append(" inner join m_deposit_account_recurring_detail rd on rd.savings_account_id = dat.savings_account_id "); @@ -1163,7 +1165,7 @@ private static final class SavingsAccountTransactionsMapper implements RowMapper sqlBuilder.append("left join m_account_transfer_transaction totran on totran.to_savings_transaction_id = tr.id "); sqlBuilder.append("left join m_payment_detail pd on tr.payment_detail_id = pd.id "); sqlBuilder.append("left join m_payment_type pt on pd.payment_type_id = pt.id "); - sqlBuilder.append("left join m_appuser au on au.id=tr.appuser_id "); + sqlBuilder.append("left join m_appuser au on au.id = tr." + CREATED_BY_DB_FIELD); this.schemaSql = sqlBuilder.toString(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java index 989c2e7f28c..0955355d2db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java @@ -144,7 +144,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @Transactional @Override public CommandProcessingResult activateFDAccount(final Long savingsId, final JsonCommand command) { - final AppUser user = this.context.authenticatedUser(); + final AppUser user = context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -160,7 +160,7 @@ public CommandProcessingResult activateFDAccount(final Long savingsId, final Jso final Set existingReversedTransactionIds = new HashSet<>(); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - final Map changes = account.activate(user, command, DateUtils.getBusinessLocalDate()); + final Map changes = account.activate(user, command); Money activationChargeAmount = getActivationCharge(account); if (!changes.isEmpty()) { final Locale locale = command.extractLocale(); @@ -172,13 +172,13 @@ public CommandProcessingResult activateFDAccount(final Long savingsId, final Jso if (portfolioAccountData == null) { final PaymentDetail paymentDetail = null; - this.depositAccountDomainService.handleFDDeposit(account, fmt, account.getActivationLocalDate(), + this.depositAccountDomainService.handleFDDeposit(account, fmt, account.getActivationDate(), amountForDeposit.getAmount(), paymentDetail); } else { final SavingsAccount fromSavingsAccount = null; boolean isRegularTransaction = false; final boolean isExceptionForBalanceCheck = false; - final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(), + final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationDate(), amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, portfolioAccountData.getId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null, account, @@ -188,9 +188,9 @@ public CommandProcessingResult activateFDAccount(final Long savingsId, final Jso final boolean isInterestTransfer = false; final LocalDate postInterestOnDate = null; if (activationChargeAmount.isGreaterThanZero()) { - payActivationCharge(account, user); + payActivationCharge(account); } - if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate(), false)) { + if (account.isBeforeLastPostingPeriod(account.getActivationDate(), false)) { final LocalDate today = DateUtils.getBusinessLocalDate(); account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false); @@ -237,11 +237,11 @@ private Money getActivationCharge(final FixedDepositAccount account) { return activationChargeAmount; } - private void payActivationCharge(final FixedDepositAccount account, AppUser user) { + private void payActivationCharge(final FixedDepositAccount account) { for (SavingsAccountCharge savingsAccountCharge : account.charges()) { if (savingsAccountCharge.isSavingsActivation()) { - account.payCharge(savingsAccountCharge, savingsAccountCharge.getAmount(account.getCurrency()), - account.getActivationLocalDate(), user, false, null); + account.payCharge(savingsAccountCharge, savingsAccountCharge.getAmount(account.getCurrency()), account.getActivationDate(), + false, null); } } } @@ -267,7 +267,7 @@ public CommandProcessingResult activateRDAccount(final Long savingsId, final Jso final Set existingReversedTransactionIds = new HashSet<>(); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - final Map changes = account.activate(user, command, DateUtils.getBusinessLocalDate()); + final Map changes = account.activate(user, command); if (!changes.isEmpty()) { final Locale locale = command.extractLocale(); @@ -277,12 +277,12 @@ public CommandProcessingResult activateRDAccount(final Long savingsId, final Jso final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService .retriveSavingsLinkedAssociation(savingsId); if (portfolioAccountData == null) { - this.depositAccountDomainService.handleRDDeposit(account, fmt, account.getActivationLocalDate(), + this.depositAccountDomainService.handleRDDeposit(account, fmt, account.getActivationDate(), amountForDeposit.getAmount(), null, isRegularTransaction); } else { final boolean isExceptionForBalanceCheck = false; final SavingsAccount fromSavingsAccount = null; - final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(), + final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationDate(), amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, portfolioAccountData.getId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null, account, @@ -314,7 +314,7 @@ public CommandProcessingResult activateRDAccount(final Long savingsId, final Jso account.updateOverduePayments(overdueUptoDate); final boolean isInterestTransfer = false; final LocalDate postInterestOnDate = null; - if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate(), false)) { + if (account.isBeforeLastPostingPeriod(account.getActivationDate(), false)) { final LocalDate today = DateUtils.getBusinessLocalDate(); account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false, postReversals); @@ -571,7 +571,7 @@ public CommandProcessingResult undoRDTransaction(final Long savingsId, final Lon checkClientOrGroupActive(account); final boolean postReversals = false; if (savingsAccountTransaction.isPostInterestCalculationRequired() - && account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), false)) { + && account.isBeforeLastPostingPeriod(savingsAccountTransaction.getTransactionDate(), false)) { account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false, postReversals); } else { @@ -620,7 +620,7 @@ public CommandProcessingResult adjustFDTransaction(final Long savingsId, @Suppre @Override public CommandProcessingResult adjustRDTransaction(final Long savingsId, final Long transactionId, final JsonCommand command) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -671,11 +671,11 @@ public CommandProcessingResult adjustRDTransaction(final Long savingsId, final L UUID refNo = UUID.randomUUID(); if (savingsAccountTransaction.isDeposit()) { final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, - paymentDetail, savingsAccountTransaction.getCreatedDate(), user, accountType); + paymentDetail, null, accountType); transaction = account.deposit(transactionDTO, false, relaxingDaysConfigForPivotDate, refNo.toString()); } else { final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, - paymentDetail, savingsAccountTransaction.getCreatedDate(), user, accountType); + paymentDetail, null, accountType); transaction = account.withdraw(transactionDTO, true, false, relaxingDaysConfigForPivotDate, refNo.toString()); } final Long newtransactionId = saveTransactionToGenerateTransactionId(transaction); @@ -683,7 +683,7 @@ public CommandProcessingResult adjustRDTransaction(final Long savingsId, final L final LocalDate postInterestOnDate = null; final boolean postReversals = false; if (account.isBeforeLastPostingPeriod(transactionDate, false) - || account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), false)) { + || account.isBeforeLastPostingPeriod(savingsAccountTransaction.getTransactionDate(), false)) { account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false, postReversals); } else { @@ -757,8 +757,7 @@ public CommandProcessingResult closeFDAccount(final Long savingsId, final JsonCo DepositAccountType.FIXED_DEPOSIT); checkClientOrGroupActive(account); - this.depositAccountDomainService.handleFDAccountClosure(account, paymentDetail, user, command, DateUtils.getBusinessLocalDate(), - changes); + this.depositAccountDomainService.handleFDAccountClosure(account, paymentDetail, user, command, changes); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { @@ -791,8 +790,7 @@ public CommandProcessingResult closeRDAccount(final Long savingsId, final JsonCo DepositAccountType.RECURRING_DEPOSIT); checkClientOrGroupActive(account); - this.depositAccountDomainService.handleRDAccountClosure(account, paymentDetail, user, command, DateUtils.getBusinessLocalDate(), - changes); + this.depositAccountDomainService.handleRDAccountClosure(account, paymentDetail, user, command, changes); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { @@ -825,8 +823,7 @@ public CommandProcessingResult prematureCloseFDAccount(final Long savingsId, fin DepositAccountType.FIXED_DEPOSIT); checkClientOrGroupActive(account); - this.depositAccountDomainService.handleFDAccountPreMatureClosure(account, paymentDetail, user, command, - DateUtils.getBusinessLocalDate(), changes); + this.depositAccountDomainService.handleFDAccountPreMatureClosure(account, paymentDetail, user, command, changes); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { @@ -868,8 +865,7 @@ public CommandProcessingResult prematureCloseRDAccount(final Long savingsId, fin } } - this.depositAccountDomainService.handleRDAccountPreMatureClosure(account, paymentDetail, user, command, - DateUtils.getBusinessLocalDate(), changes); + this.depositAccountDomainService.handleRDAccountPreMatureClosure(account, paymentDetail, user, command, changes); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { @@ -892,7 +888,7 @@ public CommandProcessingResult prematureCloseRDAccount(final Long savingsId, fin @Override public SavingsAccountTransaction initiateSavingsTransfer(final Long accountId, final LocalDate transferDate, final DepositAccountType depositAccountType) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth(); @@ -904,7 +900,7 @@ public SavingsAccountTransaction initiateSavingsTransfer(final Long accountId, f updateExistingTransactionsDetails(savingsAccount, existingTransactionIds, existingReversedTransactionIds); final SavingsAccountTransaction newTransferTransaction = SavingsAccountTransaction.initiateTransfer(savingsAccount, - savingsAccount.office(), transferDate, user); + savingsAccount.office(), transferDate); savingsAccount.addTransaction(newTransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue()); final MathContext mc = MathContext.DECIMAL64; @@ -924,7 +920,7 @@ public SavingsAccountTransaction initiateSavingsTransfer(final Long accountId, f @Override public SavingsAccountTransaction withdrawSavingsTransfer(final Long accountId, final LocalDate transferDate, final DepositAccountType depositAccountType) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -937,7 +933,7 @@ public SavingsAccountTransaction withdrawSavingsTransfer(final Long accountId, f updateExistingTransactionsDetails(savingsAccount, existingTransactionIds, existingReversedTransactionIds); final SavingsAccountTransaction withdrawtransferTransaction = SavingsAccountTransaction.withdrawTransfer(savingsAccount, - savingsAccount.office(), transferDate, user); + savingsAccount.office(), transferDate); savingsAccount.addTransaction(withdrawtransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); final boolean postReversals = false; @@ -965,7 +961,7 @@ public void rejectSavingsTransfer(final Long accountId, final DepositAccountType @Override public SavingsAccountTransaction acceptSavingsTransfer(final Long accountId, final LocalDate transferDate, final Office acceptedInOffice, final Staff fieldOfficer, final DepositAccountType depositAccountType) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -978,7 +974,7 @@ public SavingsAccountTransaction acceptSavingsTransfer(final Long accountId, fin updateExistingTransactionsDetails(savingsAccount, existingTransactionIds, existingReversedTransactionIds); final SavingsAccountTransaction acceptTransferTransaction = SavingsAccountTransaction.approveTransfer(savingsAccount, - acceptedInOffice, transferDate, user); + acceptedInOffice, transferDate); savingsAccount.addTransaction(acceptTransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); if (fieldOfficer != null) { @@ -1024,11 +1020,11 @@ public CommandProcessingResult addSavingsAccountCharge(final JsonCommand command final SavingsAccountCharge savingsAccountCharge = SavingsAccountCharge.createNewFromJson(savingsAccount, chargeDefinition, command); - if (savingsAccountCharge.getDueLocalDate() != null) { + if (savingsAccountCharge.getDueDate() != null) { // transaction date should not be on a holiday or non working day if (!this.configurationDomainService.allowTransactionsOnHolidayEnabled() - && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); @@ -1036,8 +1032,8 @@ public CommandProcessingResult addSavingsAccountCharge(final JsonCommand command } if (!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled() - && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); @@ -1080,14 +1076,14 @@ public CommandProcessingResult updateSavingsAccountCharge(final JsonCommand comm final Map changes = savingsAccountCharge.update(command); - if (savingsAccountCharge.getDueLocalDate() != null) { + if (savingsAccountCharge.getDueDate() != null) { final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); // transaction date should not be on a holiday or non working day if (!this.configurationDomainService.allowTransactionsOnHolidayEnabled() - && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); @@ -1095,8 +1091,8 @@ public CommandProcessingResult updateSavingsAccountCharge(final JsonCommand comm } if (!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled() - && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); @@ -1120,7 +1116,7 @@ public CommandProcessingResult updateSavingsAccountCharge(final JsonCommand comm @Override public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Long savingsAccountChargeId, @SuppressWarnings("unused") final DepositAccountType depositAccountType) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -1137,12 +1133,12 @@ public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Lo final Set existingReversedTransactionIds = new HashSet<>(); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - account.waiveCharge(savingsAccountChargeId, user, false); + account.waiveCharge(savingsAccountChargeId, false); boolean isInterestTransfer = false; LocalDate postInterestOnDate = null; final MathContext mc = MathContext.DECIMAL64; final boolean postReversals = false; - if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate(), false)) { + if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueDate(), false)) { final LocalDate today = DateUtils.getBusinessLocalDate(); account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false, postReversals); @@ -1249,13 +1245,13 @@ public CommandProcessingResult payCharge(final Long savingsAccountId, final Long @Override public void applyChargeDue(final Long savingsAccountChargeId, final Long accountId, @SuppressWarnings("unused") final DepositAccountType depositAccountType) { - // always use current date as transaction date for batch job - final LocalDate transactionDate = DateUtils.getBusinessLocalDate(); final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository .findOneWithNotFoundDetection(savingsAccountChargeId, accountId); - + // always use current date as transaction date for batch job + final LocalDate transactionDate = DateUtils.getBusinessLocalDate(); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd MM yyyy"); - while (transactionDate.isAfter(savingsAccountCharge.getDueLocalDate())) { + + while (DateUtils.isBefore(savingsAccountCharge.getDueDate(), transactionDate)) { payCharge(savingsAccountCharge, transactionDate, savingsAccountCharge.amoutOutstanding(), fmt); } } @@ -1263,7 +1259,7 @@ public void applyChargeDue(final Long savingsAccountChargeId, final Long account @Transactional private void payCharge(final SavingsAccountCharge savingsAccountCharge, final LocalDate transactionDate, final BigDecimal amountPaid, final DateTimeFormatter formatter) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -1275,7 +1271,7 @@ private void payCharge(final SavingsAccountCharge savingsAccountCharge, final Lo final Set existingTransactionIds = new HashSet<>(); final Set existingReversedTransactionIds = new HashSet<>(); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - account.payCharge(savingsAccountCharge, amountPaid, transactionDate, formatter, user, false, null); + account.payCharge(savingsAccountCharge, amountPaid, transactionDate, formatter, false, null); boolean isInterestTransfer = false; LocalDate postInterestOnDate = null; final MathContext mc = MathContext.DECIMAL64; @@ -1323,10 +1319,10 @@ public void updateMaturityDetails(Long depositAccountId, DepositAccountType depo if (fdAccount.isMatured() && (fdAccount.isReinvestOnClosure() || fdAccount.isTransferToSavingsOnClosure())) { DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); Map changes = new HashMap<>(); - AppUser user = context.authenticatedUser(); + final AppUser user = context.authenticatedUser(); Long toSavingsId = fdAccount.getTransferToSavingsAccountId(); - this.depositAccountDomainService.handleFDAccountMaturityClosure(fdAccount, null, user, fdAccount.maturityDate(), fmt, - fdAccount.maturityDate(), fdAccount.getOnAccountClosureId(), toSavingsId, "Apply maturity instructions", changes); + this.depositAccountDomainService.handleFDAccountMaturityClosure(fdAccount, null, user, fmt, fdAccount.maturityDate(), + fdAccount.getOnAccountClosureId(), toSavingsId, "Apply maturity instructions", changes); if (changes.get("reinvestedDepositId") != null) { Long reinvestedDepositId = (Long) changes.get("reinvestedDepositId"); @@ -1335,7 +1331,7 @@ public void updateMaturityDetails(Long depositAccountId, DepositAccountType depo .assembleFrom(reinvestedDepositId, DepositAccountType.FIXED_DEPOSIT); Money activationChargeAmount = getActivationCharge(reinvestAccount); if (activationChargeAmount.isGreaterThanZero()) { - payActivationCharge(reinvestAccount, user); + payActivationCharge(reinvestAccount); amountForDeposit = amountForDeposit.plus(activationChargeAmount); } this.depositAccountDomainService.handleFDDeposit(reinvestAccount, fmt, fdAccount.maturityDate(), @@ -1393,13 +1389,4 @@ public SavingsAccountTransaction mandatorySavingsAccountDeposit(final SavingsAcc isRegularTransaction); } - - private AppUser getAppUserIfPresent() { - AppUser user = null; - if (this.context != null) { - user = this.context.getAuthenticatedUserIfPresent(); - } - return user; - } - } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java index 0fd55c56ba5..af393f0ace6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java @@ -47,7 +47,6 @@ 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.event.business.domain.deposit.FixedDepositAccountCreateBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.deposit.RecurringDepositAccountCreateBusinessEvent; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; @@ -384,7 +383,7 @@ public CommandProcessingResult modifyFDApplication(final Long accountId, final J DepositAccountType.FIXED_DEPOSIT); checkClientOrGroupActive(account); account.modifyApplication(command, changes); - account.validateNewApplicationState(DateUtils.getBusinessLocalDate(), DepositAccountType.FIXED_DEPOSIT.resourceName()); + account.validateNewApplicationState(DepositAccountType.FIXED_DEPOSIT.resourceName()); if (!changes.isEmpty()) { updateFDAndRDCommonChanges(changes, command, account); @@ -474,7 +473,7 @@ public CommandProcessingResult modifyRDApplication(final Long accountId, final J DepositAccountType.RECURRING_DEPOSIT); checkClientOrGroupActive(account); account.modifyApplication(command, changes); - account.validateNewApplicationState(DateUtils.getBusinessLocalDate(), DepositAccountType.RECURRING_DEPOSIT.resourceName()); + account.validateNewApplicationState(DepositAccountType.RECURRING_DEPOSIT.resourceName()); if (!changes.isEmpty()) { updateFDAndRDCommonChanges(changes, command, account); @@ -638,7 +637,7 @@ public CommandProcessingResult approveApplication(final Long savingsId, final Js final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType); checkClientOrGroupActive(savingsAccount); - final Map changes = savingsAccount.approveApplication(currentUser, command, DateUtils.getBusinessLocalDate()); + final Map changes = savingsAccount.approveApplication(currentUser, command); if (!changes.isEmpty()) { this.savingAccountRepository.save(savingsAccount); @@ -708,7 +707,7 @@ public CommandProcessingResult rejectApplication(final Long savingsId, final Jso final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType); checkClientOrGroupActive(savingsAccount); - final Map changes = savingsAccount.rejectApplication(currentUser, command, DateUtils.getBusinessLocalDate()); + final Map changes = savingsAccount.rejectApplication(currentUser, command); if (!changes.isEmpty()) { this.savingAccountRepository.save(savingsAccount); @@ -742,8 +741,7 @@ public CommandProcessingResult applicantWithdrawsFromApplication(final Long savi final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType); checkClientOrGroupActive(savingsAccount); - final Map changes = savingsAccount.applicantWithdrawsFromApplication(currentUser, command, - DateUtils.getBusinessLocalDate()); + final Map changes = savingsAccount.applicantWithdrawsFromApplication(currentUser, command); if (!changes.isEmpty()) { this.savingAccountRepository.save(savingsAccount); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java index 4e10ca9d160..7bb15e9ece7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java @@ -94,7 +94,6 @@ public String schema() { @Override public SavingsAccountChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - final Long id = rs.getLong("id"); final Long chargeId = rs.getLong("chargeId"); final Long accountId = rs.getLong("accountId"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java index 6ee2687974f..a4c2a939e47 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.savings.service; +import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; import java.math.MathContext; import java.time.LocalDate; @@ -30,6 +31,7 @@ import java.util.Set; import java.util.stream.Collectors; import org.apache.fineract.infrastructure.core.domain.LocalDateInterval; +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.savings.DepositAccountType; @@ -62,7 +64,6 @@ public SavingsAccountInterestPostingServiceImpl(final SavingsHelper savingsHelpe public SavingsAccountData postInterest(final MathContext mc, final LocalDate interestPostingUpToDate, final boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth, final LocalDate postInterestOnDate, final boolean backdatedTxnsAllowedTill, final SavingsAccountData savingsAccountData) { - Money interestPostedToDate = Money.zero(savingsAccountData.getCurrency()); LocalDate startInterestDate = getStartInterestCalculationDate(savingsAccountData); @@ -84,13 +85,11 @@ public SavingsAccountData postInterest(final MathContext mc, final LocalDate int withholdTransactions.addAll(findWithHoldSavingsTransactionsWithPivotConfig(savingsAccountData)); for (final PostingPeriod interestPostingPeriod : postingPeriods) { - final LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); - if (!interestPostingTransactionDate.isAfter(interestPostingUpToDate)) { + if (!DateUtils.isAfter(interestPostingTransactionDate, interestPostingUpToDate)) { interestPostedToDate = interestPostedToDate.plus(interestEarnedToBePostedForPeriod); - final SavingsAccountTransactionData postingTransaction = findInterestPostingTransactionFor(interestPostingTransactionDate, savingsAccountData); @@ -245,7 +244,7 @@ public List calculateInterestUsing(final MathContext mc, final Lo Money periodStartingBalance; if (savingsAccountData.getStartInterestCalculationDate() != null && !savingsAccountData.getStartInterestCalculationDate().equals(savingsAccountData.getActivationLocalDate())) { - final SavingsAccountTransactionData transaction = retrieveLastTransactions(savingsAccountData); + final SavingsAccountTransactionData transaction = retrieveLastTransaction(savingsAccountData); if (transaction == null) { periodStartingBalance = Money.zero(savingsAccountData.getCurrency()); @@ -329,13 +328,8 @@ private List retrieveListOfTransactions(final Sav } protected LocalDate getLockedInUntilLocalDate(final SavingsAccountData savingsAccount) { - LocalDate lockedInUntilLocalDate = null; - if (savingsAccount.getLockedInUntilDate() != null) { - lockedInUntilLocalDate = savingsAccount.getActivationLocalDate(); - // lockedInUntilLocalDate = LocalDate.ofInstant(this.lockedInUntilDate.toInstant(), - // DateUtils.getDateTimeZoneOfTenant()); - } - return lockedInUntilLocalDate; + LocalDate lockedInUntilLocalDate = savingsAccount.getLockedInUntilDate(); + return lockedInUntilLocalDate == null ? savingsAccount.getActivationLocalDate() : lockedInUntilLocalDate; } private BigDecimal minBalanceForInterestCalculation(final SavingsAccountData savingsAccountData) { @@ -358,20 +352,17 @@ public List getTransactions(final SavingsAccountD return savingsAccountData.getSavingsAccountTransactionData(); } - private SavingsAccountTransactionData retrieveLastTransactions(final SavingsAccountData savingsAccountData) { - if (savingsAccountData.getSavingsAccountTransactionData() != null - && savingsAccountData.getSavingsAccountTransactionData().size() == 1) { - return savingsAccountData.getSavingsAccountTransactionData().get(0); + private SavingsAccountTransactionData retrieveLastTransaction(@NotNull SavingsAccountData savingsAccountData) { + List transactions = savingsAccountData.getSavingsAccountTransactionData(); + if (transactions == null || transactions.isEmpty()) { + return savingsAccountData.getLastSavingsAccountTransaction(); // what is this? } - final List listOfTransactionsSorted = new ArrayList<>(); - listOfTransactionsSorted.addAll(savingsAccountData.getSavingsAccountTransactionData()); - if (!listOfTransactionsSorted.isEmpty()) { - final SavingsAccountTransactionDataComparator transactionComparator = new SavingsAccountTransactionDataComparator(); - Collections.sort(listOfTransactionsSorted, transactionComparator); - } else { - listOfTransactionsSorted.add(savingsAccountData.getLastSavingsAccountTransaction()); + if (transactions.size() == 1) { + return transactions.get(0); } - return listOfTransactionsSorted.get(0); + final List listOfTransactionsSorted = new ArrayList<>(transactions); + listOfTransactionsSorted.sort(new SavingsAccountTransactionDataComparator()); + return listOfTransactionsSorted.get(0); // this is the first transaction, not the last } public LocalDate getStartInterestCalculationDate(final SavingsAccountData savingsAccountData) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index e6679f6162f..a512ad8c5c7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -18,6 +18,9 @@ */ package org.apache.fineract.portfolio.savings.service; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE_DB_FIELD; + import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; @@ -278,7 +281,8 @@ public List retrieveAllSavingsDataForInterestPosting(final b } sql = sql + " and (sa.interest_posted_till_date is null or sa.interest_posted_till_date <= ? ) "; - sql = sql + " order by sa.id, tr.transaction_date, tr.created_date, tr.id"; + // #audit backward compatibility + sql = sql + " order by sa.id, tr.transaction_date, tr." + CREATED_DATE_DB_FIELD + ", tr.created_date, tr.id"; List savingsAccountDataList = this.jdbcTemplate.query(sql, this.savingAccountMapperForInterestPosting, // NOSONAR new Object[] { maxSavingsId, status, pageSize, yesterday }); @@ -459,19 +463,19 @@ public List extractData(final ResultSet rs) throws SQLExcept Integer daysToDormancy = null; Integer daysToEscheat = null; - LocalDate localTenantDate = DateUtils.getBusinessLocalDate(); + LocalDate currentDate = DateUtils.getBusinessLocalDate(); if (isDormancyTrackingActive && statusEnum.equals(SavingsAccountStatusType.ACTIVE.getValue())) { if (subStatusEnum < SavingsAccountSubStatusEnum.ESCHEAT.getValue()) { - daysToEscheat = Math.toIntExact( - ChronoUnit.DAYS.between(localTenantDate, lastActiveTransactionDate.plusDays(numDaysToEscheat))); + daysToEscheat = Math + .toIntExact(ChronoUnit.DAYS.between(currentDate, lastActiveTransactionDate.plusDays(numDaysToEscheat))); } if (subStatusEnum < SavingsAccountSubStatusEnum.DORMANT.getValue()) { daysToDormancy = Math.toIntExact( - ChronoUnit.DAYS.between(localTenantDate, lastActiveTransactionDate.plusDays(numDaysToDormancy))); + ChronoUnit.DAYS.between(currentDate, lastActiveTransactionDate.plusDays(numDaysToDormancy))); } if (subStatusEnum < SavingsAccountSubStatusEnum.INACTIVE.getValue()) { daysToInactive = Math.toIntExact( - ChronoUnit.DAYS.between(localTenantDate, lastActiveTransactionDate.plusDays(numDaysToInactive))); + ChronoUnit.DAYS.between(currentDate, lastActiveTransactionDate.plusDays(numDaysToInactive))); } } final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedOnDate"); @@ -896,19 +900,19 @@ public SavingsAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") Integer daysToDormancy = null; Integer daysToEscheat = null; - LocalDate localTenantDate = DateUtils.getBusinessLocalDate(); + LocalDate currentDate = DateUtils.getBusinessLocalDate(); if (isDormancyTrackingActive && statusEnum.equals(SavingsAccountStatusType.ACTIVE.getValue())) { if (subStatusEnum < SavingsAccountSubStatusEnum.ESCHEAT.getValue()) { daysToEscheat = Math - .toIntExact(ChronoUnit.DAYS.between(localTenantDate, lastActiveTransactionDate.plusDays(numDaysToEscheat))); + .toIntExact(ChronoUnit.DAYS.between(currentDate, lastActiveTransactionDate.plusDays(numDaysToEscheat))); } if (subStatusEnum < SavingsAccountSubStatusEnum.DORMANT.getValue()) { daysToDormancy = Math - .toIntExact(ChronoUnit.DAYS.between(localTenantDate, lastActiveTransactionDate.plusDays(numDaysToDormancy))); + .toIntExact(ChronoUnit.DAYS.between(currentDate, lastActiveTransactionDate.plusDays(numDaysToDormancy))); } if (subStatusEnum < SavingsAccountSubStatusEnum.INACTIVE.getValue()) { daysToInactive = Math - .toIntExact(ChronoUnit.DAYS.between(localTenantDate, lastActiveTransactionDate.plusDays(numDaysToInactive))); + .toIntExact(ChronoUnit.DAYS.between(currentDate, lastActiveTransactionDate.plusDays(numDaysToInactive))); } } @@ -1266,10 +1270,10 @@ public SavingsAccountTransactionData retrieveDepositTransactionTemplate(final Lo @Override public Collection retrieveAllTransactions(final Long savingsId, DepositAccountType depositAccountType) { - + // #audit backward compatibility final String sql = "select " + this.transactionsMapper.schema() - + " where sa.id = ? and sa.deposit_type_enum = ? order by tr.transaction_date DESC, tr.created_date DESC, tr.id DESC"; - + + " where sa.id = ? and sa.deposit_type_enum = ? order by tr.transaction_date DESC," + " tr." + CREATED_DATE_DB_FIELD + + " DESC, tr.created_date DESC, tr.id DESC"; return this.jdbcTemplate.query(sql, this.transactionsMapper, new Object[] { savingsId, depositAccountType.getValue() }); // NOSONAR } @@ -1352,8 +1356,8 @@ private static String buildFrom() { + "left join m_account_transfer_transaction fromtran on fromtran.from_savings_transaction_id = tr.id " + "left join m_account_transfer_transaction totran on totran.to_savings_transaction_id = tr.id " + "left join m_payment_detail pd on tr.payment_detail_id = pd.id " - + "left join m_payment_type pt on pd.payment_type_id = pt.id left join m_appuser au on au.id=tr.appuser_id " - + "left join m_note nt ON nt.savings_account_transaction_id=tr.id "; + + "left join m_payment_type pt on pd.payment_type_id = pt.id left join m_appuser au on au.id= tr." + CREATED_BY_DB_FIELD + + " left join m_note nt ON nt.savings_account_transaction_id=tr.id "; } public String schema() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index e21382667f7..f0bf3b186a7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -207,7 +207,7 @@ public CommandProcessingResult activate(final Long savingsId, final JsonCommand updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - final Map changes = account.activate(user, command, DateUtils.getBusinessLocalDate()); + final Map changes = account.activate(user, command); entityDatatableChecksWritePlatformService.runTheCheckForProduct(savingsId, EntityTables.SAVINGS.getName(), StatusEnum.ACTIVATE.getCode().longValue(), EntityTables.SAVINGS.getForeignKeyColumnNameOnDatatable(), account.productId()); @@ -235,7 +235,7 @@ public CommandProcessingResult activate(final Long savingsId, final JsonCommand @Override public void processPostActiveActions(final SavingsAccount account, final DateTimeFormatter fmt, final Set existingTransactionIds, final Set existingReversedTransactionIds) { - AppUser user = getAppUserIfPresent(); + getAppUserIfPresent(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -245,13 +245,13 @@ public void processPostActiveActions(final SavingsAccount account, final DateTim boolean isRegularTransaction = false; if (amountForDeposit.isGreaterThanZero()) { boolean isAccountTransfer = false; - this.savingsAccountDomainService.handleDeposit(account, fmt, account.getActivationLocalDate(), amountForDeposit.getAmount(), - null, isAccountTransfer, isRegularTransaction, false); + this.savingsAccountDomainService.handleDeposit(account, fmt, account.getActivationDate(), amountForDeposit.getAmount(), null, + isAccountTransfer, isRegularTransaction, false); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); } - account.processAccountUponActivation(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, user); + account.processAccountUponActivation(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth); List depositAccountOnHoldTransactions = null; if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) { depositAccountOnHoldTransactions = this.depositAccountOnHoldTransactionRepository @@ -417,16 +417,16 @@ public CommandProcessingResult withdrawal(final Long savingsId, final JsonComman @Transactional @Override public CommandProcessingResult applyAnnualFee(final Long savingsAccountChargeId, final Long accountId) { - AppUser user = getAppUserIfPresent(); + getAppUserIfPresent(); final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository .findOneWithNotFoundDetection(savingsAccountChargeId, accountId); - final LocalDate todaysDate = DateUtils.getBusinessLocalDate(); + final LocalDate currentDate = DateUtils.getBusinessLocalDate(); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd MM yyyy").withZone(DateUtils.getDateTimeZoneOfTenant()); - while (todaysDate.isAfter(savingsAccountCharge.getDueLocalDate())) { - this.payCharge(savingsAccountCharge, savingsAccountCharge.getDueLocalDate(), savingsAccountCharge.amount(), fmt, user, false); + while (DateUtils.isBefore(savingsAccountCharge.getDueDate(), currentDate)) { + this.payCharge(savingsAccountCharge, savingsAccountCharge.getDueDate(), savingsAccountCharge.amount(), fmt, false); } return new CommandProcessingResultBuilder() // @@ -681,7 +681,7 @@ public CommandProcessingResult undoTransaction(final Long savingsId, final Long throw new SavingsAccountTransactionNotFoundException(savingsId, transactionId); } - this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(savingsAccountTransaction.getTransactionLocalDate(), + this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(savingsAccountTransaction.getTransactionDate(), account); if (!allowAccountTransferModification @@ -718,7 +718,7 @@ public CommandProcessingResult undoTransaction(final Long savingsId, final Long boolean postReversals = false; checkClientOrGroupActive(account); if (savingsAccountTransaction.isPostInterestCalculationRequired() - && account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), false)) { + && account.isBeforeLastPostingPeriod(savingsAccountTransaction.getTransactionDate(), false)) { account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false, postReversals); } else { @@ -746,7 +746,7 @@ public CommandProcessingResult undoTransaction(final Long savingsId, final Long @Override public CommandProcessingResult adjustSavingsTransaction(final Long savingsId, final Long transactionId, final JsonCommand command) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -808,7 +808,7 @@ public CommandProcessingResult adjustSavingsTransaction(final Long savingsId, fi boolean isInterestTransfer = false; Integer accountType = null; final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, - paymentDetail, savingsAccountTransaction.getCreatedDate(), user, accountType); + paymentDetail, null, accountType); UUID refNo = UUID.randomUUID(); if (savingsAccountTransaction.isDeposit()) { transaction = account.deposit(transactionDTO, false, relaxingDaysConfigForPivotDate, refNo.toString()); @@ -819,7 +819,7 @@ public CommandProcessingResult adjustSavingsTransaction(final Long savingsId, fi final LocalDate postInterestOnDate = null; boolean postReversals = false; if (account.isBeforeLastPostingPeriod(transactionDate, false) - || account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), false)) { + || account.isBeforeLastPostingPeriod(savingsAccountTransaction.getTransactionDate(), false)) { account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, false, postReversals); } else { @@ -927,7 +927,7 @@ public CommandProcessingResult close(final Long savingsId, final JsonCommand com List savingTransactions = account.getTransactions(); for (SavingsAccountTransaction savingTransaction : savingTransactions) { if (savingTransaction.isInterestPosting() && savingTransaction.isNotReversed() - && DateUtils.isEqual(closedDate, savingTransaction.getTransactionLocalDate())) { + && DateUtils.isEqual(closedDate, savingTransaction.getTransactionDate())) { postInterestOnClosingDate = true; break; } @@ -957,7 +957,7 @@ public CommandProcessingResult close(final Long savingsId, final JsonCommand com } - final Map accountChanges = account.close(user, command, DateUtils.getBusinessLocalDate()); + final Map accountChanges = account.close(user, command); changes.putAll(accountChanges); if (!changes.isEmpty()) { this.savingAccountRepositoryWrapper.save(account); @@ -985,7 +985,7 @@ public CommandProcessingResult close(final Long savingsId, final JsonCommand com @Override public SavingsAccountTransaction initiateSavingsTransfer(final SavingsAccount savingsAccount, final LocalDate transferDate) { - AppUser user = getAppUserIfPresent(); + getAppUserIfPresent(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -999,7 +999,7 @@ public SavingsAccountTransaction initiateSavingsTransfer(final SavingsAccount sa updateExistingTransactionsDetails(savingsAccount, existingTransactionIds, existingReversedTransactionIds); final SavingsAccountTransaction newTransferTransaction = SavingsAccountTransaction.initiateTransfer(savingsAccount, - savingsAccount.office(), transferDate, user); + savingsAccount.office(), transferDate); savingsAccount.addTransaction(newTransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue()); final MathContext mc = MathContext.DECIMAL64; @@ -1019,7 +1019,7 @@ public SavingsAccountTransaction initiateSavingsTransfer(final SavingsAccount sa @Override public SavingsAccountTransaction withdrawSavingsTransfer(final SavingsAccount savingsAccount, final LocalDate transferDate) { - AppUser user = getAppUserIfPresent(); + getAppUserIfPresent(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -1030,7 +1030,7 @@ public SavingsAccountTransaction withdrawSavingsTransfer(final SavingsAccount sa updateExistingTransactionsDetails(savingsAccount, existingTransactionIds, existingReversedTransactionIds); final SavingsAccountTransaction withdrawtransferTransaction = SavingsAccountTransaction.withdrawTransfer(savingsAccount, - savingsAccount.office(), transferDate, user); + savingsAccount.office(), transferDate); savingsAccount.addTransaction(withdrawtransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); final MathContext mc = MathContext.DECIMAL64; @@ -1058,7 +1058,7 @@ public void rejectSavingsTransfer(final SavingsAccount savingsAccount) { @Override public SavingsAccountTransaction acceptSavingsTransfer(final SavingsAccount savingsAccount, final LocalDate transferDate, final Office acceptedInOffice, final Staff fieldOfficer) { - AppUser user = getAppUserIfPresent(); + getAppUserIfPresent(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -1069,7 +1069,7 @@ public SavingsAccountTransaction acceptSavingsTransfer(final SavingsAccount savi updateExistingTransactionsDetails(savingsAccount, existingTransactionIds, existingReversedTransactionIds); final SavingsAccountTransaction acceptTransferTransaction = SavingsAccountTransaction.approveTransfer(savingsAccount, - acceptedInOffice, transferDate, user); + acceptedInOffice, transferDate); savingsAccount.addTransaction(acceptTransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); if (fieldOfficer != null) { @@ -1126,17 +1126,17 @@ public CommandProcessingResult addSavingsAccountCharge(final JsonCommand command savingsAccountCharge.setFreeWithdrawalCount(0); } - if (savingsAccountCharge.getDueLocalDate() != null) { + if (savingsAccountCharge.getDueDate() != null) { // transaction date should not be on a holiday or non working day if (!this.configurationDomainService.allowTransactionsOnHolidayEnabled() - && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday"); } if (!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled() - && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day"); } } @@ -1178,14 +1178,14 @@ public CommandProcessingResult updateSavingsAccountCharge(final JsonCommand comm final Map changes = savingsAccountCharge.update(command); - if (savingsAccountCharge.getDueLocalDate() != null) { + if (savingsAccountCharge.getDueDate() != null) { final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); // transaction date should not be on a holiday or non working day if (!this.configurationDomainService.allowTransactionsOnHolidayEnabled() - && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && this.holidayRepository.isHoliday(savingsAccount.officeId(), savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); @@ -1193,8 +1193,8 @@ public CommandProcessingResult updateSavingsAccountCharge(final JsonCommand comm } if (!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled() - && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate())) { - baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().format(fmt)) + && !this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueDate())) { + baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueDate().format(fmt)) .failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); @@ -1217,7 +1217,7 @@ public CommandProcessingResult updateSavingsAccountCharge(final JsonCommand comm @Transactional @Override public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Long savingsAccountChargeId) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); @@ -1242,13 +1242,13 @@ public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Lo updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); } - account.waiveCharge(savingsAccountChargeId, user, backdatedTxnsAllowedTill); + account.waiveCharge(savingsAccountChargeId, backdatedTxnsAllowedTill); boolean isInterestTransfer = false; LocalDate postInterestOnDate = null; final MathContext mc = MathContext.DECIMAL64; boolean postReversals = false; - if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate(), backdatedTxnsAllowedTill)) { + if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueDate(), backdatedTxnsAllowedTill)) { final LocalDate today = DateUtils.getBusinessLocalDate(); account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill, postReversals); @@ -1308,7 +1308,7 @@ public CommandProcessingResult deleteSavingsAccountCharge(final Long savingsAcco @Override public CommandProcessingResult payCharge(final Long savingsAccountId, final Long savingsAccountChargeId, final JsonCommand command) { - AppUser user = getAppUserIfPresent(); + context.authenticatedUser(); this.savingsAccountChargeDataValidator.validatePayCharge(command.json()); final Locale locale = command.extractLocale(); @@ -1344,7 +1344,7 @@ public CommandProcessingResult payCharge(final Long savingsAccountId, final Long final boolean backdatedTxnsAllowedTill = false; - SavingsAccountTransaction chargeTransaction = this.payCharge(savingsAccountCharge, transactionDate, amountPaid, fmt, user, + SavingsAccountTransaction chargeTransaction = this.payCharge(savingsAccountCharge, transactionDate, amountPaid, fmt, backdatedTxnsAllowedTill); final String noteText = command.stringValueOfParameterNamed("note"); @@ -1367,16 +1367,14 @@ public CommandProcessingResult payCharge(final Long savingsAccountId, final Long @Override public void applyChargeDue(final Long savingsAccountChargeId, final Long accountId) { // always use current date as transaction date for batch job - AppUser user = null; - final LocalDate transactionDate = DateUtils.getBusinessLocalDate(); final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository .findOneWithNotFoundDetection(savingsAccountChargeId, accountId); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd MM yyyy").withZone(DateUtils.getDateTimeZoneOfTenant()); - while (savingsAccountCharge.isNotFullyPaid() && DateUtils.isBeforeBusinessDate(savingsAccountCharge.getDueLocalDate())) { - payCharge(savingsAccountCharge, transactionDate, savingsAccountCharge.amoutOutstanding(), fmt, user, false); + while (savingsAccountCharge.isNotFullyPaid() && DateUtils.isBefore(savingsAccountCharge.getDueDate(), transactionDate)) { + payCharge(savingsAccountCharge, transactionDate, savingsAccountCharge.amoutOutstanding(), fmt, false); } } @@ -1390,8 +1388,7 @@ private SavingsAccountData fallbackPostInterest(SavingsAccountData savingsAccoun @Transactional private SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAccountCharge, final LocalDate transactionDate, - final BigDecimal amountPaid, final DateTimeFormatter formatter, final AppUser user, final boolean backdatedTxnsAllowedTill) { - + final BigDecimal amountPaid, final DateTimeFormatter formatter, final boolean backdatedTxnsAllowedTill) { final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService .isSavingsInterestPostingAtCurrentPeriodEnd(); final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth(); @@ -1409,7 +1406,7 @@ private SavingsAccountTransaction payCharge(final SavingsAccountCharge savingsAc account.validateAccountBalanceDoesNotViolateOverdraft(savingsAccountTransaction, amountPaid); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - SavingsAccountTransaction chargeTransaction = account.payCharge(savingsAccountCharge, amountPaid, transactionDate, formatter, user, + SavingsAccountTransaction chargeTransaction = account.payCharge(savingsAccountCharge, amountPaid, transactionDate, formatter, backdatedTxnsAllowedTill, null); boolean isInterestTransfer = false; LocalDate postInterestOnDate = null; @@ -1649,7 +1646,7 @@ public void setSubStatusInactive(Long savingsId) { final Set existingTransactionIds = new HashSet<>(); final Set existingReversedTransactionIds = new HashSet<>(); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); - account.setSubStatusInactive(appuserRepository.fetchSystemUser(), false); + account.setSubStatusInactive(false); this.savingAccountRepositoryWrapper.saveAndFlush(account); postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, false); } @@ -1767,16 +1764,15 @@ public CommandProcessingResult holdAmount(final Long savingsId, final JsonComman this.savingsAccountTransactionDataValidator.validateHoldAndAssembleForm(command.json(), account, submittedBy, backdatedTxnsAllowedTill); - SavingsAccountTransaction transaction = this.savingsAccountDomainService.handleHold(account, getAppUserIfPresent(), amount, - transactionDate, lienAllowed); + SavingsAccountTransaction transaction = this.savingsAccountDomainService.handleHold(account, amount, transactionDate, lienAllowed); account.holdAmount(amount); - transaction.updateRunningBalance(runningBalance); + transaction.setRunningBalance(runningBalance); final String reasonForBlock = command.stringValueOfParameterNamed(SavingsApiConstants.reasonForBlockParamName); transaction.updateReason(reasonForBlock); account.getAccountBalance(); - this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transaction.getTransactionLocalDate(), account); + this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transaction.getTransactionDate(), account); this.savingsAccountTransactionRepository.saveAndFlush(transaction); @@ -1794,14 +1790,14 @@ public CommandProcessingResult holdAmount(final Long savingsId, final JsonComman @Transactional @Override public CommandProcessingResult releaseAmount(final Long savingsId, final Long savingsTransactionId) { - final AppUser submittedBy = this.context.authenticatedUser(); + context.authenticatedUser(); SavingsAccountTransaction holdTransaction = this.savingsAccountTransactionRepository .findOneByIdAndSavingsAccountId(savingsTransactionId, savingsId); holdTransaction.updateReason(null); final SavingsAccountTransaction transaction = this.savingsAccountTransactionDataValidator - .validateReleaseAmountAndAssembleForm(holdTransaction, submittedBy); + .validateReleaseAmountAndAssembleForm(holdTransaction); final boolean backdatedTxnsAllowedTill = this.savingAccountAssembler.getPivotConfigStatus(); final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId, backdatedTxnsAllowedTill); @@ -1814,9 +1810,9 @@ public CommandProcessingResult releaseAmount(final Long savingsId, final Long sa runningBalance = runningBalance.minus(savingsOnHold); runningBalance = runningBalance.plus(transaction.getAmount()); - transaction.updateRunningBalance(runningBalance); + transaction.setRunningBalance(runningBalance); - this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transaction.getTransactionLocalDate(), account); + this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transaction.getTransactionDate(), account); account.releaseOnHoldAmount(transaction.getAmount()); this.savingsAccountTransactionRepository.saveAndFlush(transaction); @@ -1914,11 +1910,11 @@ public CommandProcessingResult unblockDebits(final Long savingsId) { private void validateTransactionsForTransfer(final SavingsAccount savingsAccount, final LocalDate transferDate) { for (SavingsAccountTransaction transaction : savingsAccount.getTransactions()) { - if ((DateUtils.isEqual(transferDate, transaction.getTransactionLocalDate()) + if ((DateUtils.isEqual(transferDate, transaction.getTransactionDate()) && DateUtils.isEqual(transferDate, transaction.getSubmittedOnDate())) - || DateUtils.isBefore(transferDate, transaction.getTransactionLocalDate())) { + || DateUtils.isBefore(transferDate, transaction.getTransactionDate())) { throw new GeneralPlatformDomainRuleException(TransferApiConstants.transferClientSavingsException, - TransferApiConstants.transferClientSavingsException, transaction.getCreatedDate(), transferDate); + TransferApiConstants.transferClientSavingsException, transaction.getCreatedDateTime(), transferDate); } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java index c78a6c34a6e..89d4d07e884 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java @@ -47,7 +47,6 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; -import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.dataqueries.data.EntityTables; import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum; import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService; @@ -320,7 +319,7 @@ public CommandProcessingResult modifyApplication(final Long savingsId, final Jso final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId, false); checkClientOrGroupActive(account); account.modifyApplication(command, changes); - account.validateNewApplicationState(DateUtils.getBusinessLocalDate(), SAVINGS_ACCOUNT_RESOURCE_NAME); + account.validateNewApplicationState(SAVINGS_ACCOUNT_RESOURCE_NAME); account.validateAccountValuesWithProduct(); if (!changes.isEmpty()) { @@ -480,7 +479,7 @@ public CommandProcessingResult approveApplication(final Long savingsId, final Js StatusEnum.APPROVE.getCode().longValue(), EntityTables.SAVINGS.getForeignKeyColumnNameOnDatatable(), savingsAccount.productId()); - final Map changes = savingsAccount.approveApplication(currentUser, command, DateUtils.getBusinessLocalDate()); + final Map changes = savingsAccount.approveApplication(currentUser, command); if (!changes.isEmpty()) { this.savingAccountRepository.save(savingsAccount); @@ -603,7 +602,7 @@ public CommandProcessingResult rejectApplication(final Long savingsId, final Jso StatusEnum.REJECTED.getCode().longValue(), EntityTables.SAVINGS.getForeignKeyColumnNameOnDatatable(), savingsAccount.productId()); - final Map changes = savingsAccount.rejectApplication(currentUser, command, DateUtils.getBusinessLocalDate()); + final Map changes = savingsAccount.rejectApplication(currentUser, command); if (!changes.isEmpty()) { this.savingAccountRepository.save(savingsAccount); @@ -640,8 +639,7 @@ public CommandProcessingResult applicantWithdrawsFromApplication(final Long savi StatusEnum.WITHDRAWN.getCode().longValue(), EntityTables.SAVINGS.getForeignKeyColumnNameOnDatatable(), savingsAccount.productId()); - final Map changes = savingsAccount.applicantWithdrawsFromApplication(currentUser, command, - DateUtils.getBusinessLocalDate()); + final Map changes = savingsAccount.applicantWithdrawsFromApplication(currentUser, command); if (!changes.isEmpty()) { this.savingAccountRepository.save(savingsAccount); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java index ccf0d5f34b9..a3eda8f4774 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java @@ -18,12 +18,16 @@ */ package org.apache.fineract.portfolio.savings.service; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_BY_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE_DB_FIELD; + import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.UUID; @@ -64,7 +68,6 @@ public class SavingsSchedularInterestPoster { @Transactional(isolation = Isolation.READ_UNCOMMITTED, rollbackFor = Exception.class) public void postInterest() throws JobExecutionException { - if (!savingAccounts.isEmpty()) { List errors = new ArrayList<>(); for (SavingsAccountData savingsAccountData : savingAccounts) { @@ -114,14 +117,14 @@ private void batchUpdateJournalEntries(final List savingsAcc savingsAccountTransactionData.setId(dataFromFetch.getId()); if (savingsAccountData.getGlAccountIdForSavingsControl() != 0 && savingsAccountData.getGlAccountIdForInterestOnSavings() != 0) { + OffsetDateTime auditDatetime = DateUtils.getAuditOffsetDateTime(); paramsForGLInsertion.add(new Object[] { savingsAccountData.getGlAccountIdForSavingsControl(), savingsAccountData.getOfficeId(), null, currencyCode, SAVINGS_TRANSACTION_IDENTIFIER + savingsAccountTransactionData.getId().toString(), savingsAccountTransactionData.getId(), null, false, null, false, savingsAccountTransactionData.getTransactionDate(), JournalEntryType.CREDIT.getValue().longValue(), savingsAccountTransactionData.getAmount(), null, JournalEntryType.CREDIT.getValue().longValue(), - savingsAccountData.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), - DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), false, BigDecimal.ZERO, BigDecimal.ZERO, null, + savingsAccountData.getId(), auditDatetime, auditDatetime, false, BigDecimal.ZERO, BigDecimal.ZERO, null, savingsAccountTransactionData.getTransactionDate(), null, userId, userId, DateUtils.getBusinessLocalDate() }); @@ -131,8 +134,7 @@ private void batchUpdateJournalEntries(final List savingsAcc savingsAccountTransactionData.getId(), null, false, null, false, savingsAccountTransactionData.getTransactionDate(), JournalEntryType.DEBIT.getValue().longValue(), savingsAccountTransactionData.getAmount(), null, JournalEntryType.DEBIT.getValue().longValue(), - savingsAccountData.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), - DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), false, BigDecimal.ZERO, BigDecimal.ZERO, null, + savingsAccountData.getId(), auditDatetime, auditDatetime, false, BigDecimal.ZERO, BigDecimal.ZERO, null, savingsAccountTransactionData.getTransactionDate(), null, userId, userId, DateUtils.getBusinessLocalDate() }); } @@ -147,16 +149,12 @@ private void batchUpdateJournalEntries(final List savingsAcc } private String batchQueryForJournalEntries() { - StringBuilder query = new StringBuilder(100); - - query.append("INSERT INTO acc_gl_journal_entry(account_id,office_id,reversal_id,currency_code,transaction_id,"); - query.append("savings_transaction_id,client_transaction_id,reversed,ref_num,manual_entry,entry_date,type_enum,"); - query.append("amount,description,entity_type_enum,entity_id,created_on_utc,"); - query.append("last_modified_on_utc,is_running_balance_calculated,office_running_balance,organization_running_balance,"); - query.append("payment_details_id,transaction_date,share_transaction_id, created_by, last_modified_by, submitted_on_date) "); - query.append("VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - - return query.toString(); + return "INSERT INTO acc_gl_journal_entry(account_id,office_id,reversal_id,currency_code,transaction_id," + + "savings_transaction_id,client_transaction_id,reversed,ref_num,manual_entry,entry_date,type_enum," + + "amount,description,entity_type_enum,entity_id,created_on_utc," + + "last_modified_on_utc,is_running_balance_calculated,office_running_balance,organization_running_balance," + + "payment_details_id,transaction_date,share_transaction_id, created_by, last_modified_by, submitted_on_date) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; } private List fetchTransactionsFromIds(final List refNo) throws DataAccessException { @@ -172,7 +170,10 @@ private void batchUpdate(final List savingsAccountDataList) List paramsForSavingsSummary = new ArrayList<>(); List paramsForTransactionUpdate = new ArrayList<>(); List transRefNo = new ArrayList<>(); + LocalDate currentDate = DateUtils.getBusinessLocalDate(); + Long userId = platformSecurityContext.authenticatedUser().getId(); for (SavingsAccountData savingsAccountData : savingsAccountDataList) { + OffsetDateTime auditTime = DateUtils.getAuditOffsetDateTime(); SavingsAccountSummaryData savingsAccountSummaryData = savingsAccountData.getSummary(); paramsForSavingsSummary.add(new Object[] { savingsAccountSummaryData.getTotalDeposits(), savingsAccountSummaryData.getTotalWithdrawals(), savingsAccountSummaryData.getTotalInterestEarned(), @@ -180,39 +181,30 @@ private void batchUpdate(final List savingsAccountDataList) savingsAccountSummaryData.getTotalFeeCharge(), savingsAccountSummaryData.getTotalPenaltyCharge(), savingsAccountSummaryData.getTotalAnnualFees(), savingsAccountSummaryData.getAccountBalance(), savingsAccountSummaryData.getTotalOverdraftInterestDerived(), savingsAccountSummaryData.getTotalWithholdTax(), - Date.from(savingsAccountSummaryData.getLastInterestCalculationDate().atStartOfDay(DateUtils.getDateTimeZoneOfTenant()) - .toInstant()), - savingsAccountSummaryData.getInterestPostedTillDate() != null - ? Date.from(savingsAccountSummaryData.getInterestPostedTillDate() - .atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()) - : Date.from(savingsAccountSummaryData.getLastInterestCalculationDate() - .atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()), - savingsAccountData.getId() }); + savingsAccountSummaryData.getLastInterestCalculationDate(), + savingsAccountSummaryData.getInterestPostedTillDate() != null ? savingsAccountSummaryData.getInterestPostedTillDate() + : savingsAccountSummaryData.getLastInterestCalculationDate(), + auditTime, userId, savingsAccountData.getId() }); List savingsAccountTransactionDataList = savingsAccountData.getSavingsAccountTransactionData(); - LocalDateTime currentDate = DateUtils.getLocalDateTimeOfTenant(); for (SavingsAccountTransactionData savingsAccountTransactionData : savingsAccountTransactionDataList) { - Date balanceEndDate = null; - if (savingsAccountTransactionData.getBalanceEndDate() != null) { - balanceEndDate = Date.from(savingsAccountTransactionData.getBalanceEndDate() - .atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()); - } if (savingsAccountTransactionData.getId() == null) { UUID uuid = UUID.randomUUID(); savingsAccountTransactionData.setRefNo(uuid.toString()); transRefNo.add(uuid.toString()); paramsForTransactionInsertion.add(new Object[] { savingsAccountData.getId(), savingsAccountData.getOfficeId(), savingsAccountTransactionData.isReversed(), savingsAccountTransactionData.getTransactionType().getId(), - savingsAccountTransactionData.getTransactionDate(), savingsAccountTransactionData.getAmount(), balanceEndDate, - savingsAccountTransactionData.getBalanceNumberOfDays(), savingsAccountTransactionData.getRunningBalance(), - savingsAccountTransactionData.getCumulativeBalance(), currentDate, 1, - savingsAccountTransactionData.isManualTransaction(), savingsAccountTransactionData.getRefNo(), - savingsAccountTransactionData.isReversalTransaction(), savingsAccountTransactionData.getOverdraftAmount(), - DateUtils.getBusinessLocalDate() }); + savingsAccountTransactionData.getTransactionDate(), savingsAccountTransactionData.getAmount(), + savingsAccountTransactionData.getBalanceEndDate(), savingsAccountTransactionData.getBalanceNumberOfDays(), + savingsAccountTransactionData.getRunningBalance(), savingsAccountTransactionData.getCumulativeBalance(), + auditTime, userId, auditTime, userId, savingsAccountTransactionData.isManualTransaction(), + savingsAccountTransactionData.getRefNo(), savingsAccountTransactionData.isReversalTransaction(), + savingsAccountTransactionData.getOverdraftAmount(), currentDate }); } else { paramsForTransactionUpdate.add(new Object[] { savingsAccountTransactionData.isReversed(), - savingsAccountTransactionData.getAmount(), savingsAccountTransactionData.getOverdraftAmount(), balanceEndDate, - savingsAccountTransactionData.getBalanceNumberOfDays(), savingsAccountTransactionData.getRunningBalance(), - savingsAccountTransactionData.getCumulativeBalance(), savingsAccountTransactionData.isReversalTransaction(), + savingsAccountTransactionData.getAmount(), savingsAccountTransactionData.getOverdraftAmount(), + savingsAccountTransactionData.getBalanceEndDate(), savingsAccountTransactionData.getBalanceNumberOfDays(), + savingsAccountTransactionData.getRunningBalance(), savingsAccountTransactionData.getCumulativeBalance(), + savingsAccountTransactionData.isReversalTransaction(), auditTime, userId, savingsAccountTransactionData.getId() }); } } @@ -240,35 +232,23 @@ private void batchUpdate(final List savingsAccountDataList) } private String batchQueryForTransactionInsertion() { - StringBuilder query = new StringBuilder(100); - query.append("INSERT INTO m_savings_account_transaction (savings_account_id, office_id, is_reversed, "); - query.append("transaction_type_enum, transaction_date, amount, balance_end_date_derived, "); - query.append("balance_number_of_days_derived, running_balance_derived, cumulative_balance_derived, "); - query.append("created_date, appuser_id, is_manual, ref_no, is_reversal, "); - query.append("overdraft_amount_derived, submitted_on_date) VALUES "); - query.append("(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - return query.toString(); - + return "INSERT INTO m_savings_account_transaction (savings_account_id, office_id, is_reversed, transaction_type_enum, transaction_date, amount, balance_end_date_derived, " + + "balance_number_of_days_derived, running_balance_derived, cumulative_balance_derived, " + CREATED_DATE_DB_FIELD + ", " + + CREATED_BY_DB_FIELD + ", " + LAST_MODIFIED_DATE_DB_FIELD + ", " + LAST_MODIFIED_BY_DB_FIELD + + ", is_manual, ref_no, is_reversal, " + + "overdraft_amount_derived, submitted_on_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; } private String batchQueryForSavingsSummaryUpdate() { - StringBuilder query = new StringBuilder(100); - query.append("update m_savings_account set total_deposits_derived=?, total_withdrawals_derived=?, "); - query.append("total_interest_earned_derived=?, total_interest_posted_derived=?, total_withdrawal_fees_derived=?, "); - query.append("total_fees_charge_derived=?, total_penalty_charge_derived=?, total_annual_fees_derived=?, "); - query.append("account_balance_derived=?, total_overdraft_interest_derived=?, total_withhold_tax_derived=?, "); - query.append("last_interest_calculation_date=?, interest_posted_till_date=? where id=? "); - return query.toString(); + return "update m_savings_account set total_deposits_derived=?, total_withdrawals_derived=?, total_interest_earned_derived=?, total_interest_posted_derived=?, total_withdrawal_fees_derived=?, " + + "total_fees_charge_derived=?, total_penalty_charge_derived=?, total_annual_fees_derived=?, account_balance_derived=?, total_overdraft_interest_derived=?, total_withhold_tax_derived=?, " + + "last_interest_calculation_date=?, interest_posted_till_date=?, " + LAST_MODIFIED_DATE_DB_FIELD + " = ?, " + + LAST_MODIFIED_BY_DB_FIELD + " = ? WHERE id=? "; } private String batchQueryForTransactionsUpdate() { - StringBuilder query = new StringBuilder(100); - query.append("UPDATE m_savings_account_transaction "); - query.append("SET is_reversed=?, "); - query.append("amount=?, overdraft_amount_derived=?, balance_end_date_derived=?, "); - query.append("balance_number_of_days_derived=?, running_balance_derived=?, cumulative_balance_derived=?, "); - query.append("is_reversal=? "); - query.append("WHERE id=?"); - return query.toString(); + return "UPDATE m_savings_account_transaction " + + "SET is_reversed=?, amount=?, overdraft_amount_derived=?, balance_end_date_derived=?, balance_number_of_days_derived=?, running_balance_derived=?, cumulative_balance_derived=?, is_reversal=?, " + + LAST_MODIFIED_DATE_DB_FIELD + " = ?, " + LAST_MODIFIED_BY_DB_FIELD + " = ? " + "WHERE id=?"; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/search/SavingsAccountTransactionsSearchServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/search/SavingsAccountTransactionsSearchServiceImpl.java index db724134d22..b307fd2fdd6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/search/SavingsAccountTransactionsSearchServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/search/SavingsAccountTransactionsSearchServiceImpl.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.savings.service.search; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE_DB_FIELD; import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME; import com.google.gson.JsonObject; @@ -87,7 +88,7 @@ public Page searchTransactions(@NotNull Long savi sortPageable = pageable.withSort(Sort.by(orders.stream() .map(e -> e.withProperty(SearchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList())); } else { - pageable = pageable.withSort(Sort.Direction.DESC, "transaction_date", "created_date", "id"); + pageable = pageable.withSort(Sort.Direction.DESC, "transaction_date", CREATED_DATE_DB_FIELD, "id"); sortPageable = pageable; } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 51f316ece86..9425481a6b9 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -147,4 +147,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0128_savings_audit.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0128_savings_audit.xml new file mode 100644 index 00000000000..89a7e7b4ab9 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0128_savings_audit.xml @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select count(*) from m_savings_account + + + + + + + + + select count(*) from m_savings_account + + + + + + + + + select count(*) from m_savings_account_transaction + + + + + + + + + select count(*) from m_savings_account_transaction + + + + + + + + + select count(*) from m_deposit_account_on_hold_transaction + + + + + + + + + select count(*) from m_deposit_account_on_hold_transaction + + + + + + + + + select count(*) from m_savings_account_charge + + + + + + + + + select count(*) from m_savings_account_charge + + + + + + + + + select count(*) from m_savings_officer_assignment_history + + + + + + + + + select count(*) from m_savings_officer_assignment_history + + + + + + + + + select count(*) from m_mandatory_savings_schedule + + + + + + + + + select count(*) from m_mandatory_savings_schedule + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandlerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandlerTest.java index 5fc70c283ca..6bdcb6433ae 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandlerTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomAuditingHandlerTest.java @@ -54,7 +54,7 @@ public void markCreated() { CustomAuditingHandler testInstance = new CustomAuditingHandler(PersistentEntities.of(mappingContext)); AbstractAuditableWithUTCDateTimeCustom targetObject = Mockito.spy(AbstractAuditableWithUTCDateTimeCustom.class); targetObject = testInstance.markCreated(targetObject); - OffsetDateTime now = OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()); + OffsetDateTime now = DateUtils.getAuditOffsetDateTime(); assertTrue(targetObject.getCreatedDate().isPresent()); assertEquals(now.getYear(), targetObject.getCreatedDate().get().getYear()); @@ -70,7 +70,7 @@ public void markModified() { CustomAuditingHandler testInstance = new CustomAuditingHandler(PersistentEntities.of(mappingContext)); AbstractAuditableWithUTCDateTimeCustom targetObject = Mockito.spy(AbstractAuditableWithUTCDateTimeCustom.class); targetObject = testInstance.markModified(targetObject); - OffsetDateTime now = OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()); + OffsetDateTime now = DateUtils.getAuditOffsetDateTime(); assertTrue(targetObject.getLastModifiedDate().isPresent()); assertEquals(now.getYear(), targetObject.getLastModifiedDate().get().getYear()); @@ -86,7 +86,7 @@ public void markModifiedOldDateTimeProvider() { CustomAuditingHandler testInstance = new CustomAuditingHandler(PersistentEntities.of(mappingContext)); AbstractAuditableCustom targetObject = Mockito.spy(AbstractAuditableCustom.class); targetObject = testInstance.markModified(targetObject); - LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault()); + LocalDateTime now = DateUtils.getLocalDateTimeOfSystem(); assertTrue(targetObject.getLastModifiedDate().isPresent()); assertEquals(now.getYear(), targetObject.getLastModifiedDate().get().getYear()); @@ -102,7 +102,7 @@ public void markCreatedOldDateTimeProvider() { CustomAuditingHandler testInstance = new CustomAuditingHandler(PersistentEntities.of(mappingContext)); AbstractAuditableCustom targetObject = Mockito.spy(AbstractAuditableCustom.class); targetObject = testInstance.markCreated(targetObject); - LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault()); + LocalDateTime now = DateUtils.getLocalDateTimeOfSystem(); assertTrue(targetObject.getCreatedDate().isPresent()); assertEquals(now.getYear(), targetObject.getCreatedDate().get().getYear()); diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProviderTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProviderTest.java index 059479e7b97..ae59614f189 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProviderTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/auditing/CustomDateTimeProviderTest.java @@ -23,7 +23,6 @@ import java.time.LocalDateTime; import java.time.OffsetDateTime; -import java.time.ZoneId; import java.time.temporal.TemporalAccessor; import java.util.Optional; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; @@ -36,14 +35,13 @@ public class CustomDateTimeProviderTest { @BeforeEach public void init() { - ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null)); } @Test public void instanceDateProvider() { Optional dateTimeProvider = CustomDateTimeProvider.INSTANCE.getNow(); - LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault()); + LocalDateTime now = DateUtils.getLocalDateTimeOfSystem(); assertTrue(dateTimeProvider.isPresent()); assertTrue(dateTimeProvider.get() instanceof LocalDateTime); @@ -56,8 +54,8 @@ public void instanceDateProvider() { @Test public void tenantDateProvider() { - Optional dateTimeProvider = CustomDateTimeProvider.TENANT.getNow(); - OffsetDateTime now = OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()); + Optional dateTimeProvider = CustomDateTimeProvider.UTC.getNow(); + OffsetDateTime now = DateUtils.getAuditOffsetDateTime(); assertTrue(dateTimeProvider.isPresent()); assertTrue(dateTimeProvider.get() instanceof OffsetDateTime); diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/service/DateUtilsTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/service/DateUtilsTest.java index d00af32dc91..c5b78065bb0 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/service/DateUtilsTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/service/DateUtilsTest.java @@ -56,22 +56,22 @@ public void getDateTimeZoneOfTenant() { @Test public void getLocalDateOfTenant() { - assertEquals(LocalDate.now(ZoneId.of("Asia/Kolkata")), DateUtils.getLocalDateOfTenant()); + assertTrue(DateUtils.isEqualTenantDate(LocalDate.now(ZoneId.of("Asia/Kolkata")))); } @Test public void getLocalDateTimeOfTenant() { - assertEquals(LocalDateTime.now(ZoneId.of("Asia/Kolkata")).truncatedTo(ChronoUnit.SECONDS), DateUtils.getLocalDateTimeOfTenant()); + assertTrue(DateUtils.isEqualTenantDateTime(LocalDateTime.now(ZoneId.of("Asia/Kolkata")), ChronoUnit.SECONDS)); } @Test public void getOffsetDateTimeOfTenant() { - assertEquals(OffsetDateTime.now(ZoneId.of("Asia/Kolkata")).truncatedTo(ChronoUnit.SECONDS), DateUtils.getOffsetDateTimeOfTenant()); + assertTrue(DateUtils.isEqualTenantDateTime(OffsetDateTime.now(ZoneId.of("Asia/Kolkata")), ChronoUnit.SECONDS)); } @Test public void getLocalDateTimeOfSystem() { - assertEquals(LocalDateTime.now(ZoneId.systemDefault()).truncatedTo(ChronoUnit.SECONDS), DateUtils.getLocalDateTimeOfSystem()); + assertTrue(DateUtils.isEqualSystemDateTime(LocalDateTime.now(ZoneId.systemDefault()), ChronoUnit.SECONDS)); } @Test @@ -83,6 +83,6 @@ public void isDateInTheFuture() { @Test public void getBusinesLocalDate() { - assertEquals(LocalDate.of(2022, 6, 12), DateUtils.getBusinessLocalDate()); + assertTrue(DateUtils.isEqualBusinessDate(LocalDate.of(2022, 6, 12))); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index f6f04309498..ab52ce6da27 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -3008,7 +3008,7 @@ public void testRunningBalanceAfterDepositReversalWithBackdateConfigurationOn() this.savingsProductHelper = new SavingsProductHelper(); this.scheduleJobHelper = new SchedulerJobHelper(requestSpec); configurationForBackdatedTransaction(); - LocalDate transactionDate = LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5); + LocalDate transactionDate = Utils.getLocalDateOfTenant().minusDays(5); final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy"); String startDate = formatter.format(transactionDate); String secondTrx = formatter.format(transactionDate.plusDays(1)); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountTransactionsSearchIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountTransactionsSearchIntegrationTest.java index ca4c287fcc9..65f9e5b012e 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountTransactionsSearchIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountTransactionsSearchIntegrationTest.java @@ -30,7 +30,6 @@ import io.restassured.specification.ResponseSpecification; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.ZoneId; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -162,7 +161,7 @@ public void testSavingsTransactionsSearchDateFromTo() throws JsonProcessingExcep @Test public void testSavingsTransactionsSearchSubmittedDateFromTo() throws JsonProcessingException { - LocalDate businessDate = LocalDate.now(ZoneId.systemDefault()); + LocalDate businessDate = Utils.getLocalDateOfTenant(); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDate); Assertions.assertNotNull(clientID); final Integer savingsId = createSavingsAccountDailyPosting(clientID, startDate); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsTest.java index 6c8bfffbff3..89747b532cc 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsTest.java @@ -18,13 +18,13 @@ */ package org.apache.fineract.integrationtests; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.format.DateTimeFormatter; import org.apache.fineract.client.models.PostSavingsAccountsAccountIdRequest; import org.apache.fineract.client.models.PostSavingsAccountsAccountIdResponse; import org.apache.fineract.client.models.PostSavingsAccountsRequest; import org.apache.fineract.client.models.PostSavingsAccountsResponse; import org.apache.fineract.integrationtests.client.IntegrationTest; +import org.apache.fineract.integrationtests.common.Utils; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -42,8 +42,8 @@ public class SavingsAccountsTest extends IntegrationTest { private static final Logger LOG = LoggerFactory.getLogger(SavingsAccountsTest.class); private final String dateFormat = "dd MMMM yyyy"; private final String locale = "en"; - private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); - private final String formattedDate = simpleDateFormat.format(new Date()); + private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(dateFormat); + private final String formattedDate = dateFormatter.format(Utils.getLocalDateOfTenant()); private int savingId = 1; @Test diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingIntegrationTest.java index 6597f6ed991..16b6411e69d 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingIntegrationTest.java @@ -27,13 +27,13 @@ import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.time.LocalDate; -import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; 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; @@ -72,7 +72,7 @@ public void setup() { @Test public void testSavingsDailyInterestPosting() { - LocalDate today = LocalDate.now(ZoneId.systemDefault()); + LocalDate today = Utils.getLocalDateOfTenant(); try { GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, true); BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, today); @@ -100,7 +100,7 @@ public void testSavingsDailyInterestPosting() { List submittedOnDateStringList = (List) interestPostingTransaction.get("submittedOnDate"); LocalDate submittedOnDate = submittedOnDateStringList.stream().collect( Collectors.collectingAndThen(Collectors.toList(), list -> LocalDate.of(list.get(0), list.get(1), list.get(2)))); - assertTrue(submittedOnDate.compareTo(today) == 0, "Submitted On Date check for Interest Posting transaction"); + assertTrue(DateUtils.isEqual(submittedOnDate, today), "Submitted On Date check for Interest Posting transaction"); } finally { GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, false); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingJobIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingJobIntegrationTest.java index 5876d53a799..61ee96503f4 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingJobIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsInterestPostingJobIntegrationTest.java @@ -27,13 +27,13 @@ import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.time.LocalDate; -import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; 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; @@ -149,7 +149,7 @@ public void testDuplicateOverdraftInterestPostingJob() { @Test public void testSavingsDailyInterestPostingJob() { - LocalDate today = LocalDate.now(ZoneId.systemDefault()); + LocalDate today = Utils.getLocalDateOfTenant(); try { GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, true); BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, today); @@ -179,7 +179,7 @@ public void testSavingsDailyInterestPostingJob() { List submittedOnDateStringList = (List) interestPostingTransaction.get("submittedOnDate"); LocalDate submittedOnDate = submittedOnDateStringList.stream().collect( Collectors.collectingAndThen(Collectors.toList(), list -> LocalDate.of(list.get(0), list.get(1), list.get(2)))); - assertTrue(submittedOnDate.compareTo(today) == 0, "Submitted On Date check for Interest Posting transaction"); + assertTrue(DateUtils.isEqual(submittedOnDate, today), "Submitted On Date check for Interest Posting transaction"); } finally { GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, false); } @@ -198,9 +198,7 @@ public void testSavingsDailyOverdraftInterestPostingJob() { this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "10000", startDate, CommonConstants.RESPONSE_RESOURCE_ID); - /*** - * Runs Post interest posting job and verify the new account created with Overdraft is posting negative interest - */ + // Runs Post interest posting job and verify the new account created with Overdraft is posting negative interest this.scheduleJobHelper.executeAndAwaitJob(jobName); Object transactionObj = this.savingsAccountHelper.getSavingsDetails(savingsId, "transactions"); ArrayList> transactions = (ArrayList>) transactionObj; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java index 445437797b2..bb8d478b736 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java @@ -37,7 +37,6 @@ import java.time.Duration; import java.time.LocalDate; import java.time.LocalTime; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -179,7 +178,7 @@ public void testApplyAnnualFeeForSavingsJobOutcome() throws InterruptedException ArrayList annualFeeDueDateAsArrayList = (ArrayList) annualFeeDetails.get("dueDate"); LocalDate nextDueDateForAnnualFee = LocalDate.of(annualFeeDueDateAsArrayList.get(0), annualFeeDueDateAsArrayList.get(1), annualFeeDueDateAsArrayList.get(2)); - LocalDate todaysDate = LocalDate.now(ZoneId.of("Asia/Kolkata")); + LocalDate todaysDate = Utils.getLocalDateOfTenant(); Truth.assertWithMessage("Verifying that all due Annual Fees have been paid").that(nextDueDateForAnnualFee) .isGreaterThan(todaysDate); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java index 3a52a10abac..b9738cf73d4 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java @@ -42,7 +42,9 @@ import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.time.ZoneId; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; @@ -374,6 +376,14 @@ public static String convertDateToURLFormat(final Calendar dateToBeConvert, fina return dateFormat.format(dateToBeConvert.getTime()); } + public static OffsetDateTime getAuditOffsetDateTime() { + return OffsetDateTime.now(ZoneOffset.UTC); + } + + public static LocalDateTime getLocalDateTimeOfSystem() { + return LocalDateTime.now(ZoneId.systemDefault()); + } + public static TimeZone getTimeZoneOfTenant() { return TimeZone.getTimeZone(TENANT_TIME_ZONE); } @@ -386,6 +396,10 @@ public static LocalDate getLocalDateOfTenant() { return LocalDate.now(getZoneIdOfTenant()); } + public static LocalDateTime getLocalDateTimeOfTenant() { + return LocalDateTime.now(getZoneIdOfTenant()); + } + public static Date convertJsonElementAsDate(JsonElement jsonElement) { if (jsonElement.isJsonArray()) { JsonArray jsonArray = jsonElement.getAsJsonArray(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/CampaignsHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/CampaignsHelper.java index 27ceb936900..b18a43eb7ed 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/CampaignsHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/CampaignsHelper.java @@ -25,7 +25,6 @@ import io.restassured.path.json.JsonPath; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; -import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.List; @@ -108,7 +107,7 @@ public String getCreateCampaignJSON(String reportName, Integer triggerType) { map.put("triggerType", triggerType); if (2 == triggerType) { map.put("recurrenceStartDate", - LocalDateTime.now(Utils.getZoneIdOfTenant()).plusMinutes(1).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))); + Utils.getLocalDateTimeOfTenant().plusMinutes(1).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))); map.put("frequency", 1); map.put("interval", "1"); } @@ -136,7 +135,7 @@ public String getUpdateCampaignJSON(String reportName, Integer triggerType) { map.put("triggerType", triggerType); if (2 == triggerType) { map.put("recurrenceStartDate", - LocalDateTime.now(Utils.getZoneIdOfTenant()).plusMinutes(1).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))); + Utils.getLocalDateTimeOfTenant().plusMinutes(1).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))); } map.put("campaignName", Utils.randomStringGenerator("Campaign_Name_", 5)); map.put("campaignType", 1);