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 35ea048b3..e733975eb 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 abstract class AbstractAuditableCustom extends AbstractPersistableCustom @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 abstract class AbstractAuditableCustom extends AbstractPersistableCustom @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 dec09e6ee..55beda888 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 static org.apache.fineract.infrastructure.core.domain.AuditableFieldsCons 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 @@ import org.springframework.data.jpa.domain.AbstractAuditable; @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 1056bde38..ca45f22d1 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 @@ package org.apache.fineract.infrastructure.core.service; 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 java.util.Locale; 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 @@ public final class DateUtils { } + // DateTime + public static ZoneId getSystemZoneId() { return ZoneId.systemDefault(); } @@ -56,27 +58,38 @@ public final class DateUtils { } 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 final class DateUtils { 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 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 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 long getDifferenceInDays(final LocalDate localDateBefore, final LocalDate localDateAfter) { - return DAYS.between(localDateBefore, localDateAfter); - } - 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 final class DateUtils { 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 final class DateUtils { 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 37a16d4f5..84d73c8e1 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 @@ public final class Group extends AbstractPersistableCustom { } public boolean isActivatedAfter(final LocalDate submittedOn) { - return getActivationLocalDate().isAfter(submittedOn); + return DateUtils.isAfter(getActivationDate(), submittedOn); } public boolean isNotActive() { @@ -267,11 +267,7 @@ public final class Group extends AbstractPersistableCustom { } 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 final class Group extends AbstractPersistableCustom { 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 final class Group extends AbstractPersistableCustom { return this.submittedOnDate; } - public LocalDate getActivationLocalDate() { + public LocalDate getActivationDate() { return this.activationDate; } @@ -494,7 +490,7 @@ public final class Group extends AbstractPersistableCustom { } public boolean isChildGroup() { - return this.parent == null ? false : true; + return this.parent != null; } @@ -503,18 +499,17 @@ public final class Group extends AbstractPersistableCustom { } 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 final class Group extends AbstractPersistableCustom { } 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 @@ public final class Group extends AbstractPersistableCustom { 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 0ff25943d..9a06951b5 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 final class SavingsAccountTransactionData implements Serializable { } 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { } } - 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { 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 final class SavingsAccountTransactionData implements Serializable { 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 1fe4df28e..5e7a36e48 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.Collection; 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 final class SavingsHelper { 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 final class SavingsHelper { 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 final class SavingsHelper { 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 @@ public final class SavingsHelper { 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 @@ public final class SavingsHelper { 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 3d460fef1..4b918c019 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 @@ package org.apache.fineract.portfolio.savings.domain.interest; 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 class CompoundInterestHelper { // 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 58b51995f..ce821427c 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.BigDecimal; 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 class EndOfDayBalance { * @return */ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, final LocalDate upToInterestCalculationDate) { - Money startingBalance = this.openingBalance; LocalDate balanceStartDate = this.date; @@ -144,7 +144,7 @@ public class EndOfDayBalance { 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 class EndOfDayBalance { } 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 class EndOfDayBalance { } 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 f65b7ce60..f0bce2b12 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 final class PostingPeriod { 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 final class PostingPeriod { 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 @@ public final class PostingPeriod { 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 @@ public final class PostingPeriod { 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 @@ public final class PostingPeriod { 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 @@ public final class PostingPeriod { 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 @@ public final class PostingPeriod { 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 ce9a54650..3a3145b37 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 java.time.LocalDate; 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 class SavingsAccountTransactionDetailsForPostingPeriod { } 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 class SavingsAccountTransactionDetailsForPostingPeriod { } public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy) { - final MonetaryCurrency currency = openingBalance.getCurrency(); Money endOfDayBalance = openingBalance.copy(); @@ -101,7 +101,7 @@ public class SavingsAccountTransactionDetailsForPostingPeriod { 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 class SavingsAccountTransactionDetailsForPostingPeriod { } } - 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 6bd37070f..6dd9fc25e 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 class Loan extends AbstractAuditableWithUTCDateTimeCustom { 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 class Loan extends AbstractAuditableWithUTCDateTimeCustom { 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 185ed2d30..ea458c8df 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 class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom { 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 0d3e8ec9b..f230d0bc8 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 class SmsCampaign extends AbstractPersistableCustom { 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 @@ public class SmsCampaign extends AbstractPersistableCustom { 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 class SmsCampaign extends AbstractPersistableCustom { } 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 class SmsCampaign extends AbstractPersistableCustom { } recurrence = constructRecurrence(command); } - } else { - recurrenceStartDate = null; } return new SmsCampaign(campaignName, campaignType.intValue(), triggerType.intValue(), report, providerId, paramValue, message, @@ -186,7 +179,6 @@ public class SmsCampaign extends AbstractPersistableCustom { } public Map update(JsonCommand command) { - final Map actualChanges = new LinkedHashMap<>(5); if (command.isChangeInStringParameterNamed(SmsCampaignValidator.campaignName, this.campaignName)) { @@ -255,7 +247,6 @@ public class SmsCampaign extends AbstractPersistableCustom { } public void activate(final AppUser currentUser, final DateTimeFormatter formatter, final LocalDate activationLocalDate) { - if (isActive()) { // handle errors if already activated final String defaultUserMessage = "Cannot activate campaign. Campaign is already active."; @@ -297,7 +288,6 @@ public class SmsCampaign extends AbstractPersistableCustom { } public void reactivate(final AppUser currentUser, final DateTimeFormatter dateTimeFormat, final LocalDate reactivateLocalDate) { - if (!isClosed()) { // handle errors if already activated final String defaultUserMessage = "Cannot reactivate campaign. Campaign must be in closed state."; @@ -384,66 +374,55 @@ public class SmsCampaign extends AbstractPersistableCustom { } 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 class SmsCampaign extends AbstractPersistableCustom { 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 fb02955da..582a4b4d8 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 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService { 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 0135ed70d..64e8aeec3 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.StringReader; 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.JsonCommand; import org.apache.fineract.infrastructure.core.api.JsonQuery; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; -import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.exception.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 class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP 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 class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP @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 class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP 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 class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP } 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 f7d755f5b..f8bfff14e 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 class CustomAuditingHandler extends AuditingHandler { 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 839b18341..e2ce5d435 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 @@ import org.springframework.data.auditing.DateTimeProvider; public enum CustomDateTimeProvider implements DateTimeProvider { - INSTANCE, TENANT; + INSTANCE, UTC; /* * (non-Javadoc) @@ -42,10 +39,10 @@ public enum CustomDateTimeProvider implements DateTimeProvider { 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 a22cf3daf..8ce3d5309 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 class InteropAccountData extends CommandProcessingResult { 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 @@ public class InteropAccountData extends CommandProcessingResult { 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 dd1106b6f..64d45ef44 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 class InteropTransactionData extends CommandProcessingResult { 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 f6d486363..1c50f0b3c 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 jakarta.validation.constraints.NotNull; 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 e07466937..828821c14 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 class InteropServiceImpl implements InteropService { 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 class InteropServiceImpl implements InteropService { @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 class InteropServiceImpl implements InteropService { 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 class InteropServiceImpl implements InteropService { } 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 class InteropServiceImpl implements InteropService { 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 class InteropServiceImpl implements InteropService { 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 51e998ec7..a61ac9638 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.CommandProcessingResult; 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 class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr 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 class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr 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 class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr 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 22887192e..974aea510 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 @@ public class InterestRateChart extends AbstractPersistableCustom { 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 @@ public class InterestRateChart extends AbstractPersistableCustom { 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 ce1e68d6e..e1a78a96d 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 class InterestRateChartFields { 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 class InterestRateChartFields { 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 class InterestRateChartFields { } 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 class InterestRateChartFields { } 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 4b9f06465..21ee7b02b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java @@ -327,7 +327,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService { if (loan.isApproved() && !loan.isDisbursed()) { final List transactions = new ArrayList<>(); for (final SavingsAccountTransaction transaction : savingsAccount.getTransactions()) { - if (!transaction.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 770652be8..1c055efd4 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 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto 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 0b3bae566..46adf4221 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.ArrayList; import java.util.Collection; import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartData; import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabData; @@ -159,12 +160,11 @@ public final class DepositAccountInterestRateChartData { 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 37b38a896..de3a62022 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 @@ package org.apache.fineract.portfolio.savings.data; 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 class SavingsAccountTransactionDTO { * @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 class SavingsAccountTransactionDTO { 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 802e4c41d..fd950926f 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 com.google.gson.reflect.TypeToken; 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 class SavingsAccountTransactionDataValidator { } 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 class SavingsAccountTransactionDataValidator { 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 class SavingsAccountTransactionDataValidator { } // 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 class SavingsAccountTransactionDataValidator { 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 class SavingsAccountTransactionDataValidator { } 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 317c6b03b..af3b000cf 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.api.JsonCommand; 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 class DepositAccountAssembler { 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 class DepositAccountAssembler { 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 class DepositAccountAssembler { 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 class DepositAccountAssembler { 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 34fe6d04f..3b29b900c 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 @@ public interface DepositAccountDomainService { BigDecimal transactionAmount, PaymentDetail paymentDetail, boolean isRegularTransaction); Long handleFDAccountClosure(FixedDepositAccount account, PaymentDetail paymentDetail, AppUser user, JsonCommand command, - LocalDate tenantsTodayDate, 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); + @Transactional + 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 16e01e30c..52290bc4c 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.api.JsonCommand; 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 @@ import org.springframework.transaction.annotation.Transactional; @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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi @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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi @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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi } // if(!processMaturityInstructionOnly) - // account.close(user, command, tenantsTodayDate, changes); + // account.close(user, command, changes); this.savingsAccountRepository.save(account); @@ -341,7 +329,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi @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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi savingsTransactionId = withdrawal.getId(); } - account.close(user, command, tenantsTodayDate, changes); + account.close(user, command, changes); this.savingsAccountRepository.save(account); @@ -456,7 +442,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi @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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi savingsTransactionId = withdrawal.getId(); } - account.prematureClosure(user, command, tenantsTodayDate, changes); + account.prematureClosure(user, command, changes); this.savingsAccountRepository.save(account); @@ -513,7 +497,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi @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 class DepositAccountDomainServiceJpa implements DepositAccountDomainServi 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 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi } } } - - 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 8f3d40b7a..36a2358aa 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 class DepositAccountInterestRateChart extends AbstractPersistableCustom { 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 029c2500c..78a5f2f80 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 jakarta.persistence.Table; 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 @@ import org.apache.fineract.portfolio.savings.DepositAccountOnHoldTransactionType @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 @@ public class DepositAccountOnHoldTransaction extends AbstractPersistableCustom { 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 class DepositAccountOnHoldTransaction extends AbstractPersistableCustom { 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 class DepositAccountOnHoldTransaction extends AbstractPersistableCustom { } } - public DepositAccountOnHoldTransactionType getTransactionType() { - return DepositAccountOnHoldTransactionType.fromInt(this.transactionType); + @Override + public Optional getCreatedDate() { + // #audit backward compatibility keep system datetime + return Optional.ofNullable(super.getCreatedDate() + .orElse(createdDateToRemove == null ? null : createdDateToRemove.atZone(getSystemZoneId()).toOffsetDateTime())); } - - public LocalDate getTransactionDate() { - return this.transactionDate; - } - } 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 1bc13d842..64553b3b4 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 class DepositAccountTermAndPreClosure extends AbstractPersistableCustom { this.depositAmount = depositAmount; } - public LocalDate getMaturityLocalDate() { + public LocalDate getMaturityDate() { return this.maturityDate; } @@ -247,7 +247,7 @@ public class DepositAccountTermAndPreClosure extends AbstractPersistableCustom { } 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 b07cd1569..2855bc1e5 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 class FixedDepositAccount extends SavingsAccount { 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 class FixedDepositAccount extends SavingsAccount { } } - 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 @@ public class FixedDepositAccount extends SavingsAccount { } 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 class FixedDepositAccount extends SavingsAccount { 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 class FixedDepositAccount extends SavingsAccount { 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 class FixedDepositAccount extends SavingsAccount { 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 class FixedDepositAccount extends SavingsAccount { 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 class FixedDepositAccount extends SavingsAccount { 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 class FixedDepositAccount extends SavingsAccount { 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 @@ public class FixedDepositAccount extends SavingsAccount { } @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 @@ public class FixedDepositAccount extends SavingsAccount { } 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 @@ public class FixedDepositAccount extends SavingsAccount { 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 f87d6140a..216770856 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 class FixedDepositProduct extends SavingsProduct { 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 f21fce256..5eea23621 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 class RecurringDepositAccount extends SavingsAccount { } 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 @@ public class RecurringDepositAccount extends SavingsAccount { 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 @@ public class RecurringDepositAccount extends SavingsAccount { 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 @@ public class RecurringDepositAccount extends SavingsAccount { 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 @@ public class RecurringDepositAccount extends SavingsAccount { } runningBalance = runningBalance.plus(transactionAmount); - transaction.updateRunningBalance(runningBalance); + transaction.setRunningBalance(runningBalance); } } // loop over transactions in reverse @@ -423,7 +423,7 @@ public class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 @@ public class RecurringDepositAccount extends SavingsAccount { } } - 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 @@ public class RecurringDepositAccount extends SavingsAccount { } @Override - public Map activate(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) { + public Map activate(final AppUser currentUser, final JsonCommand command) { + final Map actualChanges = super.activate(currentUser, command); - final Map actualChanges = super.activate(currentUser, command, tenantsTodayDate); - - 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 class RecurringDepositAccount extends SavingsAccount { } 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 class RecurringDepositAccount extends SavingsAccount { } public void updateScheduleInstallments() { - // reset all installments to process from the beginning for (RecurringDepositScheduleInstallment currentInstallment : depositScheduleInstallments()) { currentInstallment.resetDerivedFields(); @@ -923,8 +914,7 @@ public class RecurringDepositAccount extends SavingsAccount { // 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 @@ public class RecurringDepositAccount extends SavingsAccount { */ 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 @@ public class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { } 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 class RecurringDepositAccount extends SavingsAccount { .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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 @@ public class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 class RecurringDepositAccount extends SavingsAccount { 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 b332a4b2e..eef970f8d 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.ManyToOne; 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 class RecurringDepositScheduleInstallment extends AbstractAuditableCustom 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 @@ public class RecurringDepositScheduleInstallment extends AbstractAuditableCustom } 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 class RecurringDepositScheduleInstallment extends AbstractAuditableCustom 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 f9e1d7975..5abf3857e 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.configuration.service.TemporaryConfigu 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 @@ import org.springframework.util.CollectionUtils; @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 class SavingsAccount extends AbstractPersistableCustom { } 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { } 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { transaction.updateCumulativeBalanceAndDates(this.currency, endOfBalanceDate); // this transactions transaction date is end of balance date for // previous transaction. - endOfBalanceDate = transaction.transactionLocalDate().minusDays(1); + endOfBalanceDate = transaction.getTransactionDate().minusDays(1); } } } @@ -1116,7 +1115,7 @@ public class SavingsAccount extends AbstractPersistableCustom { throw new PlatformApiDataValidationException(dataValidationErrors); } - if (isDateInTheFuture(transactionDTO.getTransactionDate())) { + if (DateUtils.isDateInTheFuture(transactionDTO.getTransactionDate())) { final String defaultUserMessage = "Transaction date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg." + resourceTypeName + ".transaction.in.the.future", defaultUserMessage, "transactionDate", transactionDTO.getTransactionDate().format(transactionDTO.getFormatter())); @@ -1127,9 +1126,9 @@ public class SavingsAccount extends AbstractPersistableCustom { throw new PlatformApiDataValidationException(dataValidationErrors); } - if (transactionDTO.getTransactionDate().isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(transactionDTO.getTransactionDate(), getActivationDate())) { final Object[] defaultUserArgs = Arrays.asList(transactionDTO.getTransactionDate().format(transactionDTO.getFormatter()), - getActivationLocalDate().format(transactionDTO.getFormatter())).toArray(); + getActivationDate().format(transactionDTO.getFormatter())).toArray(); final String defaultUserMessage = "Transaction date cannot be before accounts activation date."; final ApiParameterError error = ApiParameterError.parameterError( "error.msg." + resourceTypeName + ".transaction.before.activation.date", defaultUserMessage, "transactionDate", @@ -1148,8 +1147,7 @@ public class SavingsAccount extends AbstractPersistableCustom { final Money amount = Money.of(this.currency, transactionDTO.getTransactionAmount()); final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(this, office(), transactionDTO.getPaymentDetail(), - transactionDTO.getTransactionDate(), amount, transactionDTO.getCreatedDate(), transactionDTO.getAppUser(), - savingsAccountTransactionType, refNo); + transactionDTO.getTransactionDate(), amount, savingsAccountTransactionType, refNo); if (backdatedTxnsAllowedTill) { addTransactionToExisting(transaction); @@ -1173,9 +1171,9 @@ public class SavingsAccount extends AbstractPersistableCustom { public void validatePivotDateTransaction(LocalDate transactionDate, final boolean backdatedTxnsAllowedTill, final Long relaxingDaysConfigForPivotDate, final String resourceTypeName) { if (backdatedTxnsAllowedTill) { - if (this.getSummary().getInterestPostedTillDate() != null - && transactionDate.isBefore(this.getSummary().getInterestPostedTillDate().minusDays(relaxingDaysConfigForPivotDate))) { - final Object[] defaultUserArgs = Arrays.asList(transactionDate, getActivationLocalDate()).toArray(); + if (this.getSummary().getInterestPostedTillDate() != null && DateUtils.isBefore(transactionDate, + getSummary().getInterestPostedTillDate().minusDays(relaxingDaysConfigForPivotDate))) { + final Object[] defaultUserArgs = Arrays.asList(transactionDate, getActivationDate()).toArray(); final String defaultUserMessage = "Transaction date cannot be before transactions pivot date."; final ApiParameterError error = ApiParameterError.parameterError( "error.msg." + resourceTypeName + ".transaction.before.pivot.date", defaultUserMessage, "transactionDate", @@ -1189,7 +1187,7 @@ public class SavingsAccount extends AbstractPersistableCustom { } } - public LocalDate getActivationLocalDate() { + public LocalDate getActivationDate() { return this.activatedOnDate; } @@ -1212,7 +1210,7 @@ public class SavingsAccount extends AbstractPersistableCustom { if (this.startInterestCalculationDate != null) { startInterestCalculationLocalDate = this.startInterestCalculationDate; } else { - startInterestCalculationLocalDate = getActivationLocalDate(); + startInterestCalculationLocalDate = getActivationDate(); } return startInterestCalculationLocalDate; } @@ -1223,7 +1221,6 @@ public class SavingsAccount extends AbstractPersistableCustom { public SavingsAccountTransaction withdraw(final SavingsAccountTransactionDTO transactionDTO, final boolean applyWithdrawFee, final boolean backdatedTxnsAllowedTill, final Long relaxingDaysConfigForPivotDate, String refNo) { - if (!isTransactionsAllowed()) { final String defaultUserMessage = "Transaction is not allowed. Account is not active."; @@ -1236,7 +1233,7 @@ public class SavingsAccount extends AbstractPersistableCustom { throw new PlatformApiDataValidationException(dataValidationErrors); } - if (isDateInTheFuture(transactionDTO.getTransactionDate())) { + if (DateUtils.isDateInTheFuture(transactionDTO.getTransactionDate())) { final String defaultUserMessage = "Transaction date cannot be in the future."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.savingsaccount.transaction.in.the.future", defaultUserMessage, "transactionDate", transactionDTO.getTransactionDate().format(transactionDTO.getFormatter())); @@ -1247,9 +1244,9 @@ public class SavingsAccount extends AbstractPersistableCustom { throw new PlatformApiDataValidationException(dataValidationErrors); } - if (transactionDTO.getTransactionDate().isBefore(getActivationLocalDate())) { + if (DateUtils.isBefore(transactionDTO.getTransactionDate(), getActivationDate())) { final Object[] defaultUserArgs = Arrays.asList(transactionDTO.getTransactionDate().format(transactionDTO.getFormatter()), - getActivationLocalDate().format(transactionDTO.getFormatter())).toArray(); + getActivationDate().format(transactionDTO.getFormatter())).toArray(); final String defaultUserMessage = "Transaction date cannot be before accounts activation date."; final ApiParameterError error = ApiParameterError.parameterError("error.msg.savingsaccount.transaction.before.activation.date", defaultUserMessage, "transactionDate", defaultUserArgs); @@ -1262,11 +1259,11 @@ public class SavingsAccount extends AbstractPersistableCustom { if (isAccountLocked(transactionDTO.getTransactionDate())) { final String defaultUserMessage = "Withdrawal is not allowed. No withdrawals are allowed until after " - + getLockedInUntilLocalDate().format(transactionDTO.getFormatter()); + + getLockedInUntilDate().format(transactionDTO.getFormatter()); final ApiParameterError error = ApiParameterError.parameterError( "error.msg.savingsaccount.transaction.withdrawals.blocked.during.lockin.period", defaultUserMessage, "transactionDate", transactionDTO.getTransactionDate().format(transactionDTO.getFormatter()), - getLockedInUntilLocalDate().format(transactionDTO.getFormatter())); + getLockedInUntilDate().format(transactionDTO.getFormatter())); final List dataValidationErrors = new ArrayList<>(); dataValidationErrors.add(error); @@ -1279,14 +1276,13 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { } 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { transactionAmount); } } - lastSavingsDate = transaction.transactionLocalDate(); + lastSavingsDate = transaction.getTransactionDate(); } @@ -1558,13 +1549,12 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } } } - lastSavingsDate = transaction.transactionLocalDate(); + lastSavingsDate = transaction.getTransactionDate(); } BigDecimal withdrawalFee = null; @@ -1608,22 +1598,13 @@ public class SavingsAccount extends AbstractPersistableCustom { } protected boolean isAccountLocked(final LocalDate transactionDate) { - boolean isLocked = false; - final boolean accountHasLockedInSetting = this.lockedInUntilDate != null; - if (accountHasLockedInSetting) { - isLocked = getLockedInUntilLocalDate().isAfter(transactionDate); - } - return isLocked; + return DateUtils.isBefore(transactionDate, getLockedInUntilDate()); } - protected LocalDate getLockedInUntilLocalDate() { + public LocalDate getLockedInUntilDate() { return this.lockedInUntilDate; } - private boolean isDateInTheFuture(final LocalDate transactionDate) { - return transactionDate.isAfter(DateUtils.getBusinessLocalDate()); - } - public BigDecimal getAccountBalance() { return this.summary.getAccountBalance(this.currency).getAmount(); } @@ -1651,7 +1632,7 @@ public class SavingsAccount extends AbstractPersistableCustom { final String localeAsInput = command.locale(); final String dateFormat = command.dateFormat(); - if (command.isChangeInLocalDateParameterNamed(SavingsApiConstants.submittedOnDateParamName, getSubmittedOnLocalDate())) { + if (command.isChangeInLocalDateParameterNamed(SavingsApiConstants.submittedOnDateParamName, getSubmittedOnDate())) { final String newValueAsString = command.stringValueOfParameterNamed(SavingsApiConstants.submittedOnDateParamName); actualChanges.put(SavingsApiConstants.submittedOnDateParamName, newValueAsString); actualChanges.put(SavingsApiConstants.localeParamName, localeAsInput); @@ -2100,36 +2081,26 @@ public class SavingsAccount extends AbstractPersistableCustom { final SavingsOfficerAssignmentHistory latestHistoryRecord = findLatestIncompleteHistoryRecord(); final SavingsOfficerAssignmentHistory lastAssignmentRecord = findLastAssignmentHistoryRecord(newSavingsOfficer); - // assignment date should not be less than savings account submitted - // date - if (isSubmittedOnDateAfter(assignmentDate)) { - + // assignment date should not be less than savings account submitted date + if (DateUtils.isBefore(assignmentDate, getSubmittedOnDate())) { final String errorMessage = "The Savings Officer assignment date (" + assignmentDate.toString() + ") cannot be before savings submitted date (" + getSubmittedOnDate().toString() + ")."; - throw new SavingsOfficerAssignmentDateException("cannot.be.before.savings.submitted.date", errorMessage, assignmentDate, getSubmittedOnDate()); - - } else if (lastAssignmentRecord != null && lastAssignmentRecord.isEndDateAfter(assignmentDate)) { - + } else if (lastAssignmentRecord != null && lastAssignmentRecord.isBeforeEndDate(assignmentDate)) { final String errorMessage = "The Savings Officer assignment date (" + assignmentDate + ") cannot be before previous Savings Officer unassigned date (" + lastAssignmentRecord.getEndDate() + ")."; - throw new SavingsOfficerAssignmentDateException("cannot.be.before.previous.unassignement.date", errorMessage, assignmentDate, lastAssignmentRecord.getEndDate()); - - } else if (DateUtils.getBusinessLocalDate().isBefore(assignmentDate)) { - + } else if (DateUtils.isDateInTheFuture(assignmentDate)) { final String errorMessage = "The Savings Officer assignment date (" + assignmentDate + ") cannot be in the future."; - throw new SavingsOfficerAssignmentDateException("cannot.be.a.future.date", errorMessage, assignmentDate); - } else if (latestHistoryRecord != null && this.savingsOfficer.identifiedBy(newSavingsOfficer)) { - latestHistoryRecord.updateStartDate(assignmentDate); + latestHistoryRecord.setStartDate(assignmentDate); } else if (latestHistoryRecord != null && latestHistoryRecord.matchesStartDateOf(assignmentDate)) { - latestHistoryRecord.updateSavingsOfficer(newSavingsOfficer); + latestHistoryRecord.setSavingsOfficer(newSavingsOfficer); this.savingsOfficer = newSavingsOfficer; - } else if (latestHistoryRecord != null && latestHistoryRecord.hasStartDateBefore(assignmentDate)) { + } else if (latestHistoryRecord != null && latestHistoryRecord.isBeforeStartDate(assignmentDate)) { final String errorMessage = "Savings account with identifier " + getId() + " was already assigned before date " + assignmentDate; throw new SavingsOfficerAssignmentDateException("is.before.last.assignment.date", errorMessage, getId(), assignmentDate); @@ -2138,7 +2109,7 @@ public class SavingsAccount extends AbstractPersistableCustom { // savings officer correctly changed from previous savings // officer to // new savings officer - latestHistoryRecord.updateEndDate(assignmentDate); + latestHistoryRecord.setEndDate(assignmentDate); } this.savingsOfficer = newSavingsOfficer; if (isNotSubmittedAndPendingApproval()) { @@ -2150,10 +2121,8 @@ public class SavingsAccount extends AbstractPersistableCustom { } private SavingsOfficerAssignmentHistory findLastAssignmentHistoryRecord(final Staff newSavingsOfficer) { - SavingsOfficerAssignmentHistory lastAssignmentRecordLatestEndDate = null; for (final SavingsOfficerAssignmentHistory historyRecord : this.savingsOfficerHistory) { - if (historyRecord.isCurrentRecord() && !historyRecord.isSameSavingsOfficer(newSavingsOfficer)) { lastAssignmentRecordLatestEndDate = historyRecord; break; @@ -2161,7 +2130,7 @@ public class SavingsAccount extends AbstractPersistableCustom { if (lastAssignmentRecordLatestEndDate == null) { lastAssignmentRecordLatestEndDate = historyRecord; - } else if (historyRecord.isEndDateAfter(lastAssignmentRecordLatestEndDate.getEndDate()) + } else if (historyRecord.isBeforeEndDate(lastAssignmentRecordLatestEndDate.getEndDate()) && !historyRecord.isSameSavingsOfficer(newSavingsOfficer)) { lastAssignmentRecordLatestEndDate = historyRecord; } @@ -2169,10 +2138,6 @@ public class SavingsAccount extends AbstractPersistableCustom { return lastAssignmentRecordLatestEndDate; } - public boolean isSubmittedOnDateAfter(final LocalDate compareDate) { - return this.submittedOnDate == null ? false : this.submittedOnDate.isAfter(compareDate); - } - public LocalDate getSubmittedOnDate() { return submittedOnDate; } @@ -2190,18 +2155,16 @@ public class SavingsAccount extends AbstractPersistableCustom { } public void removeSavingsOfficer(final LocalDate unassignDate) { - final SavingsOfficerAssignmentHistory latestHistoryRecord = findLatestIncompleteHistoryRecord(); if (latestHistoryRecord != null) { validateUnassignDate(latestHistoryRecord, unassignDate); - latestHistoryRecord.updateEndDate(unassignDate); + latestHistoryRecord.setEndDate(unassignDate); } this.savingsOfficer = null; } private SavingsOfficerAssignmentHistory findLatestIncompleteHistoryRecord() { - SavingsOfficerAssignmentHistory latestRecordWithNoEndDate = null; for (final SavingsOfficerAssignmentHistory historyRecord : this.savingsOfficerHistory) { if (historyRecord.isCurrentRecord()) { @@ -2213,21 +2176,13 @@ public class SavingsAccount extends AbstractPersistableCustom { } private void validateUnassignDate(final SavingsOfficerAssignmentHistory latestHistoryRecord, final LocalDate unassignDate) { - - final LocalDate today = DateUtils.getBusinessLocalDate(); - - if (latestHistoryRecord.getStartDate().isAfter(unassignDate)) { - + if (DateUtils.isBefore(unassignDate, latestHistoryRecord.getStartDate())) { final String errorMessage = "The Savings officer Unassign date(" + unassignDate + ") cannot be before its assignment date (" + latestHistoryRecord.getStartDate() + ")."; - throw new SavingsOfficerUnassignmentDateException("cannot.be.before.assignment.date", errorMessage, getId(), getSavingsOfficer().getId(), latestHistoryRecord.getStartDate(), unassignDate); - - } else if (unassignDate.isAfter(today)) { - + } else if (DateUtils.isDateInTheFuture(unassignDate)) { final String errorMessage = "The Savings Officer Unassign date (" + unassignDate + ") cannot be in the future."; - throw new SavingsOfficerUnassignmentDateException("cannot.be.a.future.date", errorMessage, unassignDate); } } @@ -2236,13 +2191,10 @@ public class SavingsAccount extends AbstractPersistableCustom { return this.currency; } - public void validateNewApplicationState(final LocalDate todayDateOfTenant, final String resourceName) { - + public void validateNewApplicationState(final String resourceName) { // validateWithdrawalFeeDetails(); // validateAnnualFeeDetails(); - final LocalDate submittedOn = getSubmittedOnLocalDate(); - final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(resourceName + SavingsApiConstants.summitalAction); @@ -2252,17 +2204,17 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } } - protected LocalDate getSubmittedOnLocalDate() { - return this.submittedOnDate; - } - - private LocalDate getApprovedOnLocalDate() { - return this.approvedOnDate; - } - public Client getClient() { return this.client; } @@ -2303,8 +2247,7 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } } - 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } } - 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 class SavingsAccount extends AbstractPersistableCustom { } } - 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 class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { } } - 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { // 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 class SavingsAccount extends AbstractPersistableCustom { } } - 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 class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { } } - 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 class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { } } - 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 @@ public class SavingsAccount extends AbstractPersistableCustom { // 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 class SavingsAccount extends AbstractPersistableCustom { } public LocalDate accountSubmittedOrActivationDate() { - return getActivationLocalDate() == null ? getSubmittedOnLocalDate() : getActivationLocalDate(); + return getActivationDate() == null ? getSubmittedOnDate() : getActivationDate(); } public DepositAccountType depositAccountType() { @@ -3348,35 +3269,29 @@ public class SavingsAccount extends AbstractPersistableCustom { } 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 class SavingsAccount extends AbstractPersistableCustom { 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 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { 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 class SavingsAccount extends AbstractPersistableCustom { } LocalDate lastransactionDate = null; if (lastTransaction != null) { - lastransactionDate = lastTransaction.transactionLocalDate(); + lastransactionDate = lastTransaction.getTransactionDate(); } return lastransactionDate; } @@ -3835,7 +3746,7 @@ public class SavingsAccount extends AbstractPersistableCustom { } LocalDate lastransactionDate = null; if (lastTransaction != null) { - lastransactionDate = lastTransaction.transactionLocalDate(); + lastransactionDate = lastTransaction.getTransactionDate(); } return lastransactionDate; } @@ -3904,10 +3815,6 @@ public class SavingsAccount extends AbstractPersistableCustom { 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 b541a2d1d..0fd16e6db 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.configuration.domain.ConfigurationDoma 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 class SavingsAccountAssembler { 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 class SavingsAccountAssembler { 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 class SavingsAccountAssembler { 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 a426596ee..8c525b208 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.LinkedHashMap; 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 @@ import org.slf4j.LoggerFactory; */ @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 class SavingsAccountCharge extends AbstractPersistableCustom { 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 @@ public class SavingsAccountCharge extends AbstractPersistableCustom { return value.compareTo(BigDecimal.ZERO) > 0; } - public LocalDate getDueLocalDate() { + public LocalDate getDueDate() { return this.dueDate; } @@ -754,17 +756,13 @@ public class SavingsAccountCharge extends AbstractPersistableCustom { 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 class SavingsAccountCharge extends AbstractPersistableCustom { 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 class SavingsAccountCharge extends AbstractPersistableCustom { } 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 06f0db995..81bece8b8 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.List; 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 @@ public interface SavingsAccountDomainService { 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 f0457fea7..ad8a8c175 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.SavingsAccountTransactionType; 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 class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi 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 class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi 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 class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi 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 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi 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 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi 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 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi @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 class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi final MathContext mc = new MathContext(15, MoneyHelper.getRoundingMode()); for (SavingsAccountTransaction savingsAccountTransaction : savingsAccountTransactions) { if (savingsAccountTransaction.isPostInterestCalculationRequired() - && account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), backdatedTxnsAllowedTill)) { + && account.isBeforeLastPostingPeriod(savingsAccountTransaction.getTransactionDate(), backdatedTxnsAllowedTill)) { account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill, postReversals); @@ -330,7 +317,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi account.calculateInterestUsing(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill, postReversals); } - account.validatePivotDateTransaction(savingsAccountTransaction.getLastTransactionDate(), backdatedTxnsAllowedTill, + account.validatePivotDateTransaction(savingsAccountTransaction.getTransactionDate(), backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate, "savingsaccount"); account.validateAccountBalanceDoesNotBecomeNegativeMinimal(savingsAccountTransaction.getAmount(), false); account.activateAccountBasedOnBalance(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java index c8586c6cd..03880fb60 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java @@ -216,7 +216,7 @@ public final class SavingsAccountSummary { 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 @@ public final class SavingsAccountSummary { } 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 2f33cbf4e..6910fadcb 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 jakarta.persistence.Table; 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.EndOfDayBalance; 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 @@ import org.springframework.util.CollectionUtils; */ @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 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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,21 +303,51 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { 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); + 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.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, 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, amount, isReversed, isManualTransaction, lienTransaction, refNo); + } + + public static SavingsAccountTransaction releaseAmount(SavingsAccountTransaction accountTransaction, LocalDate transactionDate) { + return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail, + SavingsAccountTransactionType.AMOUNT_RELEASE.getValue(), transactionDate, accountTransaction.amount, + accountTransaction.reversed, accountTransaction.isManualTransaction, accountTransaction.lienTransaction, + accountTransaction.refNo); + } + + public static SavingsAccountTransaction reversal(SavingsAccountTransaction accountTransaction) { + SavingsAccountTransaction sat = copyTransaction(accountTransaction); + sat.reversed = false; + sat.setReversalTransaction(true); + sat.originalTxnId = accountTransaction.getId(); + return sat; } public static void updateTaxDetails(final Map taxDetails, @@ -325,71 +360,142 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { } } - 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); + public SavingsAccount getSavingsAccount() { + return this.savingsAccount; } - 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); - } - - 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 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); - } - - public static SavingsAccountTransaction releaseAmount(SavingsAccountTransaction accountTransaction, LocalDate transactionDate, - LocalDateTime createdDate, final AppUser appUser) { - return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail, - SavingsAccountTransactionType.AMOUNT_RELEASE.getValue(), transactionDate, createdDate, accountTransaction.amount, - accountTransaction.reversed, appUser, accountTransaction.isManualTransaction, accountTransaction.lienTransaction, - accountTransaction.refNo); - } - - public static SavingsAccountTransaction reversal(SavingsAccountTransaction accountTransaction) { - SavingsAccountTransaction sat = copyTransaction(accountTransaction); - sat.reversed = false; - sat.setReversalTransaction(true); - sat.originalTxnId = accountTransaction.getId(); - return sat; - - } - - 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { return !isReversed(); } - public boolean isReversed() { - return this.reversed; - } - public boolean isTransferInitiation() { return getTransactionType().isTransferInitiation(); } @@ -466,14 +568,6 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { } 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 final class SavingsAccountTransaction extends AbstractPersistableCustom { } 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 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { 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 3527db7fe..d526246c5 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; } - return compareResult; + 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 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 995bd3d52..6060339d9 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 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom { 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 class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom { return this.savingsOfficer.identifiedBy(staff); } - public void updateStartDate(final LocalDate startDate) { - this.startDate = startDate; - } - - public void updateEndDate(final LocalDate endDate) { - this.endDate = endDate; - } - - public boolean matchesStartDateOf(final LocalDate matchingDate) { - return getStartDate().isEqual(matchingDate); - } - public LocalDate getStartDate() { return this.startDate; } - public boolean hasStartDateBefore(final LocalDate matchingDate) { - return matchingDate.isBefore(getStartDate()); + public void setStartDate(final LocalDate startDate) { + this.startDate = startDate; } - public boolean isCurrentRecord() { - return this.endDate == null; + public LocalDate getEndDate() { + return this.endDate; + } + + public void setEndDate(final LocalDate endDate) { + this.endDate = endDate; + } + + public boolean matchesStartDateOf(final LocalDate matchingDate) { + return DateUtils.isEqual(matchingDate, getStartDate()); + } + + public boolean isBeforeStartDate(final LocalDate matchingDate) { + return DateUtils.isBefore(matchingDate, getStartDate()); } /** @@ -100,12 +114,25 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom { * @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 d32db1c09..64cc452ce 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 @@ package org.apache.fineract.portfolio.savings.jobs.generaterdschedule; 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 class GenerateRdScheduleConfig { @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 a555afd04..e49ffe3ce 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 class GenerateRdScheduleTasklet implements Tasklet { 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 c9698b5ad..693560685 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 class DepositAccountReadPlatformServiceImpl implements DepositAccountRead 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 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead 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 989c2e7f2..0955355d2 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo } } - 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo } 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo } 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo @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 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements 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 class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo 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 0fd55c56b..af393f0ac 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.GeneralPlatformDomainRu import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; -import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.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 class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 4e10ca9d1..7bb15e9ec 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 class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou @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 6ee268797..a4c2a939e 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.Map; 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 class SavingsAccountInterestPostingServiceImpl implements SavingsAccountI 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 class SavingsAccountInterestPostingServiceImpl implements SavingsAccountI 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 class SavingsAccountInterestPostingServiceImpl implements SavingsAccountI 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 @@ public class SavingsAccountInterestPostingServiceImpl implements SavingsAccountI } 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 class SavingsAccountInterestPostingServiceImpl implements SavingsAccountI 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 e6679f616..a512ad8c5 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 class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead } 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 class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead 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 class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead 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 class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead @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 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead + "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 e21382667..f0bf3b186 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi throw new SavingsAccountTransactionNotFoundException(savingsId, transactionId); } - this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(savingsAccountTransaction.getTransactionLocalDate(), + this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(savingsAccountTransaction.getTransactionDate(), account); if (!allowAccountTransferModification @@ -718,7 +718,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi } - 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi } 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi @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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi 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 c78a6c34a..89d4d07e8 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.CommandProcessingResultBuild 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 class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl 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 ccf0d5f34..a3eda8f47 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 @@ public class SavingsSchedularInterestPoster { 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 @@ public class SavingsSchedularInterestPoster { 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 @@ public class SavingsSchedularInterestPoster { } 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 @@ public class SavingsSchedularInterestPoster { 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 @@ public class SavingsSchedularInterestPoster { 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 @@ public class SavingsSchedularInterestPoster { } 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 db724134d..b307fd2fd 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 class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou 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 51f316ece..9425481a6 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 000000000..89a7e7b4a --- /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 5fc70c283..6bdcb6433 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 class CustomAuditingHandlerTest { 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 class CustomAuditingHandlerTest { 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 class CustomAuditingHandlerTest { 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 class CustomAuditingHandlerTest { 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 059479e7b..ae59614f1 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 static org.junit.jupiter.api.Assertions.assertTrue; 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 class CustomDateTimeProviderTest { @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 d00af32dc..c5b78065b 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 class DateUtilsTest { @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 class DateUtilsTest { @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 f6f043094..ab52ce6da 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 class ClientSavingsIntegrationTest { 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 ca4c287fc..65f9e5b01 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.RequestSpecification; 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 class SavingsAccountTransactionsSearchIntegrationTest { @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 6c8bfffbf..89747b532 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 6597f6ed9..16b6411e6 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.http.ContentType; 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 class SavingsInterestPostingIntegrationTest { @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 class SavingsInterestPostingIntegrationTest { 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 5876d53a7..61ee96503 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.http.ContentType; 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 class SavingsInterestPostingJobIntegrationTest { @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 class SavingsInterestPostingJobIntegrationTest { 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 class SavingsInterestPostingJobIntegrationTest { 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 445437797..bb8d478b7 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.text.SimpleDateFormat; 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 class SchedulerJobsTestResults { 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 3a52a10ab..b9738cf73 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.ParseException; 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 final class Utils { 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 final class Utils { 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 27ceb9369..b18a43eb7 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 com.google.gson.Gson; 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 class CampaignsHelper { 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 class CampaignsHelper { 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);