FINERACT-1955: Timezone handling of Savings account
This commit is contained in:
+2
-2
@@ -67,7 +67,7 @@ public abstract class AbstractAuditableCustom extends AbstractPersistableCustom
|
||||
|
||||
@Override
|
||||
public Optional<LocalDateTime> 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<LocalDateTime> getLastModifiedDate() {
|
||||
return null == this.lastModifiedDate ? Optional.empty() : Optional.of(this.lastModifiedDate);
|
||||
return Optional.ofNullable(this.lastModifiedDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
-13
@@ -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<Long, Long, OffsetDateTime> {
|
||||
|
||||
@@ -67,33 +69,36 @@ public abstract class AbstractAuditableWithUTCDateTimeCustom extends AbstractPer
|
||||
private OffsetDateTime lastModifiedDate;
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Optional<Long> getCreatedBy() {
|
||||
return Optional.ofNullable(this.createdBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Optional<OffsetDateTime> 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<Long> getLastModifiedBy() {
|
||||
return Optional.ofNullable(this.lastModifiedBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Optional<OffsetDateTime> 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);
|
||||
}
|
||||
}
|
||||
|
||||
+195
-18
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<ApiParameterError> 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);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -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<Map<String, Object>> savingsChargesPaidData = new ArrayList<>();
|
||||
for (final SavingsAccountChargesPaidByData chargePaidBy : this.chargesPaidByData) {
|
||||
|
||||
+6
-7
@@ -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;
|
||||
|
||||
+2
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -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);
|
||||
|
||||
+15
-17
@@ -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;
|
||||
|
||||
+4
-4
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user