FINERACT-2081: Fix inconsistent transaction processing order

This commit is contained in:
Adam Saghy
2024-11-11 12:32:21 +01:00
parent 832b84f574
commit 39da68820b
21 changed files with 74 additions and 86 deletions
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.delinquency.validator;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import lombok.Data;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
import org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyAction;
@@ -44,8 +45,8 @@ public class LoanDelinquencyActionData {
loanDelinquencyAction.getCreatedBy().ifPresent(this::setCreatedById);
loanDelinquencyAction.getLastModifiedBy().ifPresent(this::setUpdatedById);
this.createdOn = loanDelinquencyAction.getCreatedDateTime();
this.lastModifiedOn = loanDelinquencyAction.getLastModifiedDateTime();
this.createdOn = loanDelinquencyAction.getCreatedDate().orElse(DateUtils.getAuditOffsetDateTime());
this.lastModifiedOn = loanDelinquencyAction.getLastModifiedDate().orElse(DateUtils.getAuditOffsetDateTime());
}
}
@@ -84,10 +84,7 @@ public final class DisbursementData implements Comparable<DisbursementData> {
@Override
public int compareTo(final DisbursementData obj) {
if (obj == null) {
return -1;
}
return DateUtils.compare(obj.expectedDisbursementDate, this.expectedDisbursementDate);
return DateUtils.compareWithNullsLast(obj.expectedDisbursementDate, this.expectedDisbursementDate);
}
public boolean isDueForDisbursement(LoanScheduleType loanScheduleType, final LocalDate fromDate, final LocalDate toDate) {
@@ -1041,22 +1041,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
}
public boolean happenedBefore(LoanTransaction loanTransaction) {
// compare transaction date, creation date and then transaction id
if (DateUtils.isBefore(getTransactionDate(), loanTransaction.getTransactionDate())) {
return true;
}
if (DateUtils.isEqual(getTransactionDate(), loanTransaction.getTransactionDate())) {
if (DateUtils.isBefore(getCreatedDateTime(), loanTransaction.getCreatedDateTime())) {
return true;
}
if (DateUtils.isEqual(getCreatedDateTime(), loanTransaction.getCreatedDateTime())) {
if (getId().compareTo(loanTransaction.getId()) < 0) {
return true;
}
}
}
return false;
return LoanTransactionComparator.INSTANCE.compare(this, loanTransaction) < 0;
}
public boolean isOverPaid() {
@@ -22,7 +22,8 @@ import java.util.Comparator;
import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Sort loan transactions by transaction date, created date and transaction type placing
* Sort loan transactions by transaction date, submitted date, created date, transaction type placing, lastly compare
* ids
*/
public class LoanTransactionComparator implements Comparator<LoanTransaction> {
@@ -30,22 +31,27 @@ public class LoanTransactionComparator implements Comparator<LoanTransaction> {
@Override
public int compare(final LoanTransaction o1, final LoanTransaction o2) {
int result = DateUtils.compare(o1.getTransactionDate(), o2.getTransactionDate());
int result = DateUtils.compareWithNullsLast(o1.getTransactionDate(), o2.getTransactionDate());
if (result != 0) {
return result;
}
// For transactions bearing the same transaction date, we sort transactions based on created date (when
// available) after which sorting for waivers takes place
result = o1.getCreatedDate().isPresent()
? (o2.getCreatedDate().isPresent() ? DateUtils.compare(o1.getCreatedDateTime(), o2.getCreatedDateTime()) : -1)
: (o2.getCreatedDate().isPresent() ? 1 : 0);
// Accrual activity as last
if (o1.isAccrualActivity() != o2.isAccrualActivity()) {
return o1.isAccrualActivity() ? 1 : -1;
}
result = DateUtils.compareWithNullsLast(o1.getSubmittedOnDate(), o2.getSubmittedOnDate());
if (result != 0) {
return result;
}
// equal transaction dates
result = DateUtils.compareWithNullsLast(o1.getCreatedDate(), o2.getCreatedDate());
if (result != 0) {
return result;
}
// income posting takes priority
if (o1.isIncomePosting() != o2.isIncomePosting()) {
return o1.isIncomePosting() ? -1 : 1;
}
// waive takes priority
if (o1.isWaiver() != o2.isWaiver()) {
return o1.isWaiver() ? -1 : 1;
}