FINERACT-2080: use enums instead of integers in Loan, LoanProduct and LoanTransaction
This commit is contained in:
+2
-1
@@ -19,6 +19,7 @@
|
||||
package org.apache.fineract.accounting.producttoaccountmapping.service;
|
||||
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
|
||||
@@ -29,7 +30,7 @@ public interface ProductToGLAccountMappingWritePlatformService {
|
||||
void createSavingProductToGLAccountMapping(Long savingProductId, JsonCommand command, DepositAccountType accountType);
|
||||
|
||||
Map<String, Object> updateLoanProductToGLAccountMapping(Long loanProductId, JsonCommand command, boolean accountingRuleChanged,
|
||||
int accountingRuleTypeId);
|
||||
AccountingRuleType accountingRuleTypeId);
|
||||
|
||||
Map<String, Object> updateSavingsProductToGLAccountMapping(Long savingsProductId, JsonCommand command, boolean accountingRuleChanged,
|
||||
int accountingRuleTypeId, DepositAccountType accountType);
|
||||
|
||||
+2
-2
@@ -380,14 +380,14 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
|
||||
}
|
||||
|
||||
private void validateLoanStatus(LoanDataForExternalTransfer loanDataForExternalTransfer, boolean isDelayedSettlementEnabled) {
|
||||
LoanStatus loanStatus = LoanStatus.fromInt(loanDataForExternalTransfer.getLoanStatus());
|
||||
LoanStatus loanStatus = loanDataForExternalTransfer.getLoanStatus();
|
||||
if (!getValidLoanStatusList(isDelayedSettlementEnabled).contains(loanStatus)) {
|
||||
throw new ExternalAssetOwnerInitiateTransferException(String.format("Loan status %s is not valid for transfer.", loanStatus));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLoanStatusIntermediarySale(LoanDataForExternalTransfer loanDataForExternalTransfer) {
|
||||
LoanStatus loanStatus = LoanStatus.fromInt(loanDataForExternalTransfer.getLoanStatus());
|
||||
LoanStatus loanStatus = loanDataForExternalTransfer.getLoanStatus();
|
||||
if (!ACTIVE_LOAN_STATUSES.contains(loanStatus)) {
|
||||
throw new ExternalAssetOwnerInitiateTransferException(String.format("Loan status %s is not valid for transfer.", loanStatus));
|
||||
}
|
||||
|
||||
+5
-5
@@ -185,7 +185,7 @@ public class ExternalAssetOwnersWriteServiceTest {
|
||||
.thenReturn(Optional.of(testContext.loanDataForExternalTransfer));
|
||||
when(testContext.externalAssetOwnerRepository.findByExternalId(any(ExternalId.class)))
|
||||
.thenReturn(Optional.of(testContext.externalAssetOwner));
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue());
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus);
|
||||
when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true);
|
||||
|
||||
// when
|
||||
@@ -209,7 +209,7 @@ public class ExternalAssetOwnersWriteServiceTest {
|
||||
// given
|
||||
final JsonCommand command = createJsonCommand(testContext.jsonCommand, testContext.loanId);
|
||||
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue());
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus);
|
||||
when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true);
|
||||
when(testContext.loanRepository.findLoanDataForExternalTransferByLoanId(testContext.loanId))
|
||||
.thenReturn(Optional.of(testContext.loanDataForExternalTransfer));
|
||||
@@ -242,7 +242,7 @@ public class ExternalAssetOwnersWriteServiceTest {
|
||||
// given
|
||||
final JsonCommand command = createJsonCommand(testContext.jsonCommand, testContext.loanId);
|
||||
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue());
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus);
|
||||
when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true);
|
||||
when(testContext.loanRepository.findLoanDataForExternalTransferByLoanId(testContext.loanId))
|
||||
.thenReturn(Optional.of(testContext.loanDataForExternalTransfer));
|
||||
@@ -278,7 +278,7 @@ public class ExternalAssetOwnersWriteServiceTest {
|
||||
// given
|
||||
final JsonCommand command = createJsonCommand(testContext.jsonCommand, testContext.loanId);
|
||||
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue());
|
||||
when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus);
|
||||
when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true);
|
||||
when(testContext.loanRepository.findLoanDataForExternalTransferByLoanId(testContext.loanId))
|
||||
.thenReturn(Optional.of(testContext.loanDataForExternalTransfer));
|
||||
@@ -924,7 +924,7 @@ public class ExternalAssetOwnersWriteServiceTest {
|
||||
|
||||
lenient().when(loanDataForExternalTransfer.getId()).thenReturn(loanId);
|
||||
lenient().when(loanDataForExternalTransfer.getExternalId()).thenReturn(new ExternalId(externalLoanId));
|
||||
lenient().when(loanDataForExternalTransfer.getLoanStatus()).thenReturn(LoanStatus.ACTIVE.getValue());
|
||||
lenient().when(loanDataForExternalTransfer.getLoanStatus()).thenReturn(LoanStatus.ACTIVE);
|
||||
lenient().when(loanDataForExternalTransfer.getLoanProductId()).thenReturn(loanProductId);
|
||||
lenient().when(loanDataForExternalTransfer.getLoanProductShortName()).thenReturn(loanProductShortName);
|
||||
}
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ package org.apache.fineract.cob.data;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@@ -28,7 +29,7 @@ public class LoanDataForExternalTransfer {
|
||||
|
||||
Long id;
|
||||
ExternalId externalId;
|
||||
Integer loanStatus;
|
||||
LoanStatus loanStatus;
|
||||
Long loanProductId;
|
||||
String loanProductShortName;
|
||||
}
|
||||
|
||||
+2
-2
@@ -266,7 +266,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
||||
final MonetaryCurrency loanCurrency = loan.getCurrency();
|
||||
LoanRepaymentScheduleInstallment latestInstallment = loan.getLastLoanRepaymentScheduleInstallment();
|
||||
List<LoanTransaction> chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null,
|
||||
LoanTransactionType.CHARGEBACK.getValue());
|
||||
LoanTransactionType.CHARGEBACK);
|
||||
LocalDate overdueSinceDate = null;
|
||||
CollectionData collectionData = CollectionData.template();
|
||||
BigDecimal outstandingAmount = BigDecimal.ZERO;
|
||||
@@ -324,7 +324,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
||||
BigDecimal delinquentPenalty = BigDecimal.ZERO;
|
||||
|
||||
List<LoanTransaction> chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null,
|
||||
LoanTransactionType.CHARGEBACK.getValue());
|
||||
LoanTransactionType.CHARGEBACK);
|
||||
BigDecimal amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
|
||||
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
||||
|
||||
|
||||
+1
-1
@@ -207,7 +207,7 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite
|
||||
}
|
||||
|
||||
private void validateActiveLoan(Loan loan) {
|
||||
if (!Objects.equals(loan.getLoanStatus(), ACTIVE.getValue())) {
|
||||
if (!Objects.equals(loan.getLoanStatus(), ACTIVE)) {
|
||||
throw new GeneralPlatformDomainRuleException("loan.must.be.active",
|
||||
"Operations on interest pauses are restricted to active loans.");
|
||||
}
|
||||
|
||||
+10
-10
@@ -181,16 +181,16 @@ public interface LoanApiConstants {
|
||||
String INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE = "interestRecognitionOnDisbursementDate";
|
||||
|
||||
// Loan Summary Transaction Types
|
||||
List<Integer> LOAN_SUMMARY_TRANSACTION_TYPES = List.of(LoanTransactionType.CHARGE_ADJUSTMENT.getValue(), //
|
||||
LoanTransactionType.CHARGEBACK.getValue(), //
|
||||
LoanTransactionType.CREDIT_BALANCE_REFUND.getValue(), //
|
||||
LoanTransactionType.DOWN_PAYMENT.getValue(), //
|
||||
LoanTransactionType.GOODWILL_CREDIT.getValue(), //
|
||||
LoanTransactionType.INTEREST_PAYMENT_WAIVER.getValue(), //
|
||||
LoanTransactionType.INTEREST_REFUND.getValue(), //
|
||||
LoanTransactionType.MERCHANT_ISSUED_REFUND.getValue(), //
|
||||
LoanTransactionType.PAYOUT_REFUND.getValue(), //
|
||||
LoanTransactionType.REPAYMENT.getValue() //
|
||||
List<LoanTransactionType> LOAN_SUMMARY_TRANSACTION_TYPES = List.of(LoanTransactionType.CHARGE_ADJUSTMENT, //
|
||||
LoanTransactionType.CHARGEBACK, //
|
||||
LoanTransactionType.CREDIT_BALANCE_REFUND, //
|
||||
LoanTransactionType.DOWN_PAYMENT, //
|
||||
LoanTransactionType.GOODWILL_CREDIT, //
|
||||
LoanTransactionType.INTEREST_PAYMENT_WAIVER, //
|
||||
LoanTransactionType.INTEREST_REFUND, //
|
||||
LoanTransactionType.MERCHANT_ISSUED_REFUND, //
|
||||
LoanTransactionType.PAYOUT_REFUND, //
|
||||
LoanTransactionType.REPAYMENT //
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class LoanStatusEnumData {
|
||||
public interface Mapper {
|
||||
|
||||
default LoanStatusEnumData map(Loan source) {
|
||||
return LoanEnumerations.status(source.getPlainStatus());
|
||||
return LoanEnumerations.status(source.getStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -20,11 +20,12 @@ package org.apache.fineract.portfolio.loanaccount.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Data;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
|
||||
@Data
|
||||
public class LoanTransactionBalance {
|
||||
|
||||
private final Integer transactionType;
|
||||
private final LoanTransactionType transactionType;
|
||||
private final boolean reversed;
|
||||
private final boolean manuallyAdjustedOrReversed;
|
||||
private final BigDecimal amount;
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class AccountingRuleTypeConverter implements AttributeConverter<AccountingRuleType, Integer> {
|
||||
|
||||
@Override
|
||||
public Integer convertToDatabaseColumn(AccountingRuleType attribute) {
|
||||
return attribute == null ? null : attribute.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountingRuleType convertToEntityAttribute(Integer dbData) {
|
||||
return AccountingRuleType.fromInt(dbData);
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -50,8 +50,7 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
||||
LoanStatus oldStatus = loan.getStatus();
|
||||
LoanStatus newStatus = getNextStatus(loanEvent, loan);
|
||||
if (newStatus != null) {
|
||||
Integer newPlainStatus = newStatus.getValue();
|
||||
loan.setLoanStatus(newPlainStatus);
|
||||
loan.setLoanStatus(newStatus);
|
||||
|
||||
if (isNotLoanCreation(loanEvent)) {
|
||||
// in case of Loan creation, a LoanCreatedBusinessEvent is also raised, no need to send a status change
|
||||
@@ -85,12 +84,11 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
||||
}
|
||||
|
||||
private LoanStatus getNextStatus(LoanEvent loanEvent, Loan loan) {
|
||||
Integer plainFrom = loan.getPlainStatus();
|
||||
if (loanEvent.equals(LoanEvent.LOAN_CREATED) && plainFrom == null) {
|
||||
LoanStatus from = loan.getStatus();
|
||||
if (loanEvent.equals(LoanEvent.LOAN_CREATED) && from == null) {
|
||||
return submittedTransition();
|
||||
}
|
||||
|
||||
LoanStatus from = loan.getStatus();
|
||||
LoanStatus newState = null;
|
||||
|
||||
switch (loanEvent) {
|
||||
|
||||
+18
-24
@@ -28,6 +28,7 @@ import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
@@ -183,8 +184,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
@JoinColumn(name = "glim_id")
|
||||
private GroupLoanIndividualMonitoringAccount glim;
|
||||
|
||||
@Enumerated
|
||||
@Column(name = "loan_type_enum", nullable = false)
|
||||
private Integer loanType;
|
||||
private AccountType loanType;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "product_id", nullable = false)
|
||||
@@ -227,12 +229,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
private Integer termFrequency;
|
||||
|
||||
@Setter()
|
||||
@Enumerated
|
||||
@Column(name = "term_period_frequency_enum", nullable = false)
|
||||
private Integer termPeriodFrequencyType;
|
||||
private PeriodFrequencyType termPeriodFrequencyType;
|
||||
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
@Column(name = "loan_status_id", nullable = false)
|
||||
private Integer loanStatus;
|
||||
private LoanStatus loanStatus;
|
||||
|
||||
@Setter()
|
||||
@Column(name = "sync_disbursement_with_meeting")
|
||||
@@ -435,7 +438,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
|
||||
@Setter
|
||||
@Column(name = "loan_sub_status_id")
|
||||
private Integer loanSubStatus;
|
||||
private LoanSubStatus loanSubStatus;
|
||||
|
||||
@Column(name = "is_topup", nullable = false)
|
||||
private boolean isTopup = false;
|
||||
@@ -553,7 +556,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
}
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.loanType = loanType.getValue();
|
||||
this.loanType = loanType;
|
||||
this.fund = fund;
|
||||
this.loanOfficer = loanOfficer;
|
||||
this.loanPurpose = loanPurpose;
|
||||
@@ -562,11 +565,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
this.transactionProcessingStrategyName = transactionProcessingStrategy.getName();
|
||||
|
||||
this.loanProduct = loanProduct;
|
||||
if (loanStatus != null) {
|
||||
this.loanStatus = loanStatus.getValue();
|
||||
} else {
|
||||
this.loanStatus = null;
|
||||
}
|
||||
this.loanStatus = loanStatus;
|
||||
if (loanCharges != null && !loanCharges.isEmpty()) {
|
||||
this.charges = associateChargesWithThisLoan(loanCharges);
|
||||
this.summary = updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||
@@ -607,10 +606,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
|
||||
// Add net get net disbursal amount from charges and principal
|
||||
this.netDisbursalAmount = this.approvedPrincipal.subtract(deriveSumTotalOfChargesDueAtDisbursement());
|
||||
this.loanStatus = LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue();
|
||||
this.loanStatus = LoanStatus.SUBMITTED_AND_PENDING_APPROVAL;
|
||||
this.externalId = externalId;
|
||||
this.termFrequency = loanApplicationTerms.getLoanTermFrequency();
|
||||
this.termPeriodFrequencyType = loanApplicationTerms.getLoanTermPeriodFrequencyType().getValue();
|
||||
this.termPeriodFrequencyType = loanApplicationTerms.getLoanTermPeriodFrequencyType();
|
||||
this.expectedDisbursementDate = loanApplicationTerms.getExpectedDisbursementDate();
|
||||
this.expectedFirstRepaymentOnDate = loanApplicationTerms.getRepaymentStartFromDate();
|
||||
this.interestChargedFromDate = loanApplicationTerms.getInterestChargedFromDate();
|
||||
@@ -1827,10 +1826,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
}
|
||||
|
||||
public LoanStatus getStatus() {
|
||||
return this.loanStatus == null ? null : LoanStatus.fromInt(this.loanStatus);
|
||||
}
|
||||
|
||||
public Integer getPlainStatus() {
|
||||
return this.loanStatus;
|
||||
}
|
||||
|
||||
@@ -2450,11 +2445,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
}
|
||||
|
||||
public boolean isGroupLoan() {
|
||||
return AccountType.fromInt(this.loanType).isGroupAccount();
|
||||
return this.loanType.isGroupAccount();
|
||||
}
|
||||
|
||||
public boolean isJLGLoan() {
|
||||
return AccountType.fromInt(this.loanType).isJLGAccount();
|
||||
return this.loanType.isJLGAccount();
|
||||
}
|
||||
|
||||
public void updateInterestRateFrequencyType() {
|
||||
@@ -2738,7 +2733,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
|
||||
public LoanApplicationTerms constructLoanApplicationTerms(final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
final Integer loanTermFrequency = this.termFrequency;
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType);
|
||||
NthDayType nthDayType = null;
|
||||
DayOfWeekType dayOfWeekType = null;
|
||||
final List<DisbursementData> disbursementData = new ArrayList<>();
|
||||
@@ -2782,7 +2776,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
interestChargedFromDate = getDisbursementDate();
|
||||
}
|
||||
|
||||
return LoanApplicationTerms.assembleFrom(scheduleGeneratorDTO.getCurrency(), loanTermFrequency, loanTermPeriodFrequencyType,
|
||||
return LoanApplicationTerms.assembleFrom(scheduleGeneratorDTO.getCurrency(), loanTermFrequency, this.termPeriodFrequencyType,
|
||||
nthDayType, dayOfWeekType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(),
|
||||
scheduleGeneratorDTO.getCalculatedRepaymentsStartingFromDate(), getInArrearsTolerance(), this.loanRepaymentScheduleDetail,
|
||||
this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData, this.maxOutstandingLoanBalance,
|
||||
@@ -3386,7 +3380,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
public boolean isForeclosure() {
|
||||
boolean isForeClosure = false;
|
||||
if (this.loanSubStatus != null) {
|
||||
isForeClosure = LoanSubStatus.fromInt(loanSubStatus).isForeclosed();
|
||||
isForeClosure = loanSubStatus.isForeclosed();
|
||||
}
|
||||
|
||||
return isForeClosure;
|
||||
@@ -3464,15 +3458,15 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
}
|
||||
|
||||
public boolean hasInvalidLoanType() {
|
||||
return AccountType.fromInt(this.loanType).isInvalid();
|
||||
return getLoanType().isInvalid();
|
||||
}
|
||||
|
||||
public boolean isIndividualLoan() {
|
||||
return AccountType.fromInt(this.loanType).isIndividualAccount();
|
||||
return getLoanType().isIndividualAccount();
|
||||
}
|
||||
|
||||
public AccountType getLoanType() {
|
||||
return AccountType.fromInt(loanType);
|
||||
return this.loanType == null ? AccountType.INVALID : this.loanType;
|
||||
}
|
||||
|
||||
public void adjustNetDisbursalAmount(BigDecimal adjustedAmount) {
|
||||
|
||||
+3
-2
@@ -26,7 +26,8 @@ import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface LoanAccrualActivityRepository extends Repository<Loan, Long> {
|
||||
|
||||
@Query("select loan.id from Loan loan left join LoanTransaction lt on lt.loan = loan and lt.typeOf = 32 and lt.reversed = false and lt.dateOf = :currentDate inner join LoanRepaymentScheduleInstallment rs on rs.loan = loan and rs.isDownPayment = false and rs.additional = false and rs.dueDate = :currentDate where loan.loanRepaymentScheduleDetail.enableAccrualActivityPosting = true and loan.loanStatus = 300 and lt.id is null ")
|
||||
Set<Long> fetchLoanIdsForAccrualActivityPosting(@Param("currentDate") LocalDate currentDate);
|
||||
@Query("select loan.id from Loan loan left join LoanTransaction lt on lt.loan = loan and lt.typeOf = :loanType and lt.reversed = false and lt.dateOf = :currentDate inner join LoanRepaymentScheduleInstallment rs on rs.loan = loan and rs.isDownPayment = false and rs.additional = false and rs.dueDate = :currentDate where loan.loanRepaymentScheduleDetail.enableAccrualActivityPosting = true and loan.loanStatus = :loanStatus and lt.id is null ")
|
||||
Set<Long> fetchLoanIdsForAccrualActivityPosting(@Param("currentDate") LocalDate currentDate,
|
||||
@Param("loanType") LoanTransactionType loanTransactionType, @Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ public interface LoanRepaymentScheduleInstallmentRepository
|
||||
lrs.loan.loanProduct.delinquencyBucket IS NOT NULL
|
||||
GROUP BY lrs.loan
|
||||
""")
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") Integer loanStatus,
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") LoanStatus loanStatus,
|
||||
@Param("businessDate") LocalDate businessDate, @Param("obligationsMet") boolean obligationsMet);
|
||||
|
||||
@Query("""
|
||||
@@ -60,7 +60,7 @@ public interface LoanRepaymentScheduleInstallmentRepository
|
||||
lrs.loan.id NOT IN :loanIds
|
||||
GROUP BY lrs.loan
|
||||
""")
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") Integer loanStatus,
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") LoanStatus loanStatus,
|
||||
@Param("businessDate") LocalDate businessDate, @Param("obligationsMet") boolean obligationsMet,
|
||||
@Param("loanIds") List<Long> loanIds);
|
||||
|
||||
|
||||
+68
-57
@@ -22,10 +22,12 @@ import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.cob.data.LoanDataForExternalTransfer;
|
||||
import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo;
|
||||
import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
@@ -68,43 +70,43 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
String FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP = "Select loan.loanProduct.id from Loan loan where "
|
||||
+ "loan.group.id = :groupId and loan.loanStatus = :loanStatus and loan.client.id is NULL group by loan.loanProduct.id";
|
||||
|
||||
String DOES_CLIENT_HAVE_NON_CLOSED_LOANS = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.client.id = :clientId and loan.loanStatus in (100,200,300,303,304,700)";
|
||||
String DOES_CLIENT_HAVE_LOANS_WITH_STATUSES = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.client.id = :clientId and loan.loanStatus in :loanStatuses";
|
||||
|
||||
String DOES_PRODUCT_HAVE_NON_CLOSED_LOANS = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.loanProduct.id = :productId and loan.loanStatus in (100,200,300,303,304,700)";
|
||||
String DOES_PRODUCT_HAVE_LOANS_WITH_STATUSES = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.loanProduct.id = :productId and loan.loanStatus in :loanStatuses";
|
||||
|
||||
String FIND_NON_CLOSED_BY_ACCOUNT_NUMBER = "select loan from Loan loan where loan.accountNumber = :accountNumber and loan.loanStatus in (100,200,300,303,304)";
|
||||
String FIND_LOANS_BY_ACCOUNT_NUMBER_AND_STATUSES = "select loan from Loan loan where loan.accountNumber = :accountNumber and loan.loanStatus in :loanStatuses";
|
||||
|
||||
String FIND_ALL_NON_CLOSED = "select loan.id from Loan loan where loan.loanStatus in (100,200,300,303,304)";
|
||||
String FIND_ALL_BY_STATUSES = "select loan.id from Loan loan where loan.loanStatus in :loanStatuses";
|
||||
|
||||
String FIND_NON_CLOSED_LOAN_THAT_BELONGS_TO_CLIENT = "select loan from Loan loan where loan.id = :loanId and loan.loanStatus = 300 and loan.client.id = :clientId";
|
||||
String FIND_LOAN_BY_CLIENT_AND_STATUS = "select loan from Loan loan where loan.id = :loanId and loan.loanStatus = :loanStatus and loan.client.id = :clientId";
|
||||
|
||||
String FIND_BY_ACCOUNT_NUMBER = "select loan from Loan loan where loan.accountNumber = :accountNumber";
|
||||
|
||||
String FIND_LOAN_DATA_FOR_EXTERNAL_TRANSFER = "select new org.apache.fineract.cob.data.LoanDataForExternalTransfer(loan.id, loan.externalId, loan.loanStatus, loan.loanProduct.id, loan.loanProduct.shortName) from Loan loan where loan.id = :loanId";
|
||||
String EXISTS_NON_CLOSED_BY_EXTERNAL_LOAN_ID = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.externalId = :externalLoanId and loan.loanStatus in (100,200,300,303,304)";
|
||||
String EXISTS_BY_EXTERNAL_LOAN_ID_AND_STATUSES = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.externalId = :externalLoanId and loan.loanStatus in :loanStatuses";
|
||||
|
||||
String FIND_ID_BY_EXTERNAL_ID = "SELECT loan.id FROM Loan loan WHERE loan.externalId = :externalId";
|
||||
|
||||
String FIND_IDS_BY_EXTERNAL_IDS = "SELECT loan.id FROM Loan loan WHERE loan.externalId IN :externalIds ORDER BY loan.id ASC";
|
||||
|
||||
// should follow the logic of `FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE` query
|
||||
String FIND_OLDEST_COB_PROCESSED_LOAN = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.loanStatus in (100,200,300,303,304) and loan.lastClosedBusinessDate = (select min(l.lastClosedBusinessDate) from Loan l where l"
|
||||
+ ".loanStatus in (100,200,300,303,304) and l.lastClosedBusinessDate < :cobBusinessDate)";
|
||||
// should follow the logic of `FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE` query
|
||||
String FIND_OLDEST_COB_PROCESSED_LOAN = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.loanStatus in :loanStatuses and loan.lastClosedBusinessDate = (select min(l.lastClosedBusinessDate) from Loan l where l"
|
||||
+ ".loanStatus in :loanStatuses and l.lastClosedBusinessDate < :cobBusinessDate)";
|
||||
|
||||
String FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in (100,200,300,303,304) and (loan.lastClosedBusinessDate < :cobBusinessDate or "
|
||||
String FIND_ALL_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS_AND_STATUSES = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in :loanStatuses and (loan.lastClosedBusinessDate < :cobBusinessDate or "
|
||||
+ "loan.lastClosedBusinessDate is null)";
|
||||
|
||||
String FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in (100,200,300,303,304) and (:cobBusinessDate = loan.lastClosedBusinessDate or loan.lastClosedBusinessDate is NULL)";
|
||||
String FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in :loanStatuses and (:cobBusinessDate = loan.lastClosedBusinessDate or loan.lastClosedBusinessDate is NULL)";
|
||||
|
||||
String FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in (100,200,300,303,304) and :cobBusinessDate = loan.lastClosedBusinessDate";
|
||||
String FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in (100,200,300,303,304) and loan.lastClosedBusinessDate < :cobBusinessDate";
|
||||
String FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in :loanStatuses and :cobBusinessDate = loan.lastClosedBusinessDate";
|
||||
String FIND_ALL_LOANS_BEHIND_BY_LOAN_IDS_AND_STATUSES = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in :loanStatuses and loan.lastClosedBusinessDate < :cobBusinessDate";
|
||||
|
||||
String FIND_ALL_STAYED_LOCKED_BY_COB_BUSINESS_DATE = "select loan.id, loan.externalId, loan.accountNumber from LoanAccountLock lock left join Loan loan on lock.loanId = loan.id where lock.lockPlacedOnCobBusinessDate = :cobBusinessDate";
|
||||
|
||||
String FIND_ALL_LOAN_IDS_BY_STATUS_ID = "SELECT loan.id FROM Loan loan WHERE loan.loanStatus = :statusId";
|
||||
String FIND_ALL_LOAN_IDS_BY_STATUS = "SELECT loan.id FROM Loan loan WHERE loan.loanStatus = :loanStatus";
|
||||
|
||||
String LOANS_FOR_ACCRUAL = "select l from Loan l left join l.loanInterestRecalculationDetails recalcDetails "
|
||||
+ "where l.loanStatus = 300 and l.isNpa = false and l.chargedOff = false "
|
||||
+ "where l.loanStatus = :loanStatus and l.isNpa = false and l.chargedOff = false "
|
||||
+ "and l.loanProduct.accountingRule = :accountingType "
|
||||
+ "and (recalcDetails.isCompoundingToBePostedAsTransaction is null or recalcDetails.isCompoundingToBePostedAsTransaction = false) "
|
||||
+ "and (exists (select ls.id from LoanRepaymentScheduleInstallment ls where ls.loan.id = l.id and ls.isDownPayment = false "
|
||||
@@ -119,17 +121,17 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
|
||||
@Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
|
||||
List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId,
|
||||
@Param("loanType") Integer loanType);
|
||||
@Param("loanType") AccountType loanType);
|
||||
|
||||
@Query(FIND_CLIENT_OR_JLG_LOANS_DISBURSED_AFTER)
|
||||
List<Loan> getClientOrJLGLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("clientId") Long clientId);
|
||||
|
||||
@Query(FIND_MAX_GROUP_LOAN_COUNTER_QUERY)
|
||||
Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") Integer loanType);
|
||||
Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") AccountType loanType);
|
||||
|
||||
@Query(FIND_MAX_GROUP_LOAN_PRODUCT_COUNTER_QUERY)
|
||||
Integer getMaxGroupLoanProductCounter(@Param("productId") Long productId, @Param("groupId") Long groupId,
|
||||
@Param("loanType") Integer loanType);
|
||||
@Param("loanType") AccountType loanType);
|
||||
|
||||
@Query(FIND_MAX_CLIENT_OR_JLG_LOAN_COUNTER_QUERY)
|
||||
Integer getMaxClientOrJLGLoanCounter(@Param("clientId") Long clientId);
|
||||
@@ -139,14 +141,14 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
|
||||
@Query(FIND_GROUP_LOANS_TO_UPDATE)
|
||||
List<Loan> getGroupLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("groupId") Long groupId,
|
||||
@Param("groupLoanType") Integer groupLoanType);
|
||||
@Param("groupLoanType") AccountType groupLoanType);
|
||||
|
||||
@Query(FIND_CLIENT_OR_JLG_LOANS_TO_UPDATE)
|
||||
List<Loan> getClientOrJLGLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("clientId") Long clientId);
|
||||
|
||||
@Query(FIND_GROUP_LOANS_TO_UPDATE_LOANPRODUCT_COUNTER)
|
||||
List<Loan> getGroupLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter,
|
||||
@Param("groupId") Long groupId, @Param("groupLoanType") Integer groupLoanType);
|
||||
@Param("groupId") Long groupId, @Param("groupLoanType") AccountType groupLoanType);
|
||||
|
||||
@Query(FIND_CLIENT_LOANS_TO_UPDATE_LOANPRODUCT_COUNTER)
|
||||
List<Loan> getClientLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter,
|
||||
@@ -157,7 +159,7 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
|
||||
@Query("select loan from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and loan.loanStatus IN :loanStatuses")
|
||||
List<Loan> findByClientIdAndGroupIdAndLoanStatus(@Param("clientId") Long clientId, @Param("groupId") Long groupId,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses);
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query("select loan from Loan loan where loan.client.id = :clientId")
|
||||
List<Loan> findLoanByClientId(@Param("clientId") Long clientId);
|
||||
@@ -170,37 +172,41 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
|
||||
@Query("select loan from Loan loan where loan.id IN :ids and loan.loanStatus IN :loanStatuses and loan.loanType IN :loanTypes")
|
||||
List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes);
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses, @Param("loanTypes") Collection<AccountType> loanTypes);
|
||||
|
||||
@Query("select loan.id from Loan loan where loan.actualDisbursementDate > :disbursalDate order by loan.actualDisbursementDate")
|
||||
List<Long> getLoansDisbursedAfter(@Param("disbursalDate") LocalDate disbursalDate);
|
||||
|
||||
@Query("select loan from Loan loan where loan.client.office.id IN :officeIds and loan.loanStatus IN :loanStatuses")
|
||||
List<Loan> findByClientOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses);
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query("select loan from Loan loan where loan.group.office.id IN :officeIds and loan.loanStatus IN :loanStatuses")
|
||||
List<Loan> findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses);
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
/*** FIXME: Add more appropriate names for the query ***/
|
||||
@Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_CLIENT)
|
||||
List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus);
|
||||
List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
@Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP)
|
||||
List<Long> findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus);
|
||||
List<Long> findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
@Query(DOES_CLIENT_HAVE_NON_CLOSED_LOANS)
|
||||
boolean doNonClosedLoanAccountsExistForClient(@Param("clientId") Long clientId);
|
||||
@Query(DOES_CLIENT_HAVE_LOANS_WITH_STATUSES)
|
||||
boolean doLoanAccountsWithLoansInStatusesExistForClient(@Param("clientId") Long clientId,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(DOES_PRODUCT_HAVE_NON_CLOSED_LOANS)
|
||||
boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long productId);
|
||||
@Query(DOES_PRODUCT_HAVE_LOANS_WITH_STATUSES)
|
||||
boolean doLoanAccountsWithLoansInStatusesExistForProduct(@Param("productId") Long productId,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_NON_CLOSED_BY_ACCOUNT_NUMBER)
|
||||
Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String accountNumber);
|
||||
@Query(FIND_LOANS_BY_ACCOUNT_NUMBER_AND_STATUSES)
|
||||
Loan findLoanByAccountNumberAndStatuses(@Param("accountNumber") String accountNumber,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_NON_CLOSED_LOAN_THAT_BELONGS_TO_CLIENT)
|
||||
Loan findNonClosedLoanThatBelongsToClient(@Param("loanId") Long loanId, @Param("clientId") Long clientId);
|
||||
@Query(FIND_LOAN_BY_CLIENT_AND_STATUS)
|
||||
Loan findLoanByClientAndStatus(@Param("loanId") Long loanId, @Param("clientId") Long clientId,
|
||||
@Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
@Query(FIND_BY_ACCOUNT_NUMBER)
|
||||
Loan findLoanAccountByAccountNumber(@Param("accountNumber") String accountNumber);
|
||||
@@ -208,13 +214,14 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
@Query(FIND_LOAN_DATA_FOR_EXTERNAL_TRANSFER)
|
||||
Optional<LoanDataForExternalTransfer> findLoanDataForExternalTransferByLoanId(@Param("loanId") Long loanId);
|
||||
|
||||
@Query(EXISTS_NON_CLOSED_BY_EXTERNAL_LOAN_ID)
|
||||
boolean existsNonClosedLoanByExternalLoanId(@Param("externalLoanId") ExternalId externalLoanId);
|
||||
@Query(EXISTS_BY_EXTERNAL_LOAN_ID_AND_STATUSES)
|
||||
boolean existsLoanByExternalLoanIdAndStatuses(@Param("externalLoanId") ExternalId externalLoanId,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
boolean existsByExternalId(@Param("externalId") ExternalId externalId);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED)
|
||||
List<Long> findAllNonClosedLoanIds();
|
||||
@Query(FIND_ALL_BY_STATUSES)
|
||||
List<Long> findAllLoanIdsByStatuses(@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_ID_BY_EXTERNAL_ID)
|
||||
Long findIdByExternalId(@Param("externalId") ExternalId externalId);
|
||||
@@ -222,38 +229,42 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
@Query(FIND_IDS_BY_EXTERNAL_IDS)
|
||||
List<Long> findIdsByExternalIds(@Param("externalIds") List<ExternalId> externalIds);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS)
|
||||
List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanIds") List<Long> loanIds);
|
||||
@Query(FIND_ALL_LOANS_BEHIND_BY_LOAN_IDS_AND_STATUSES)
|
||||
List<LoanIdAndLastClosedBusinessDate> findAllLoansBehindByLoanIdsAndStatuses(@Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanIds") List<Long> loanIds, @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS)
|
||||
List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindOrNullByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanIds") List<Long> loanIds);
|
||||
@Query(FIND_ALL_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS_AND_STATUSES)
|
||||
List<LoanIdAndLastClosedBusinessDate> findAllLoansBehindOrNullByLoanIdsAndStatuses(@Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanIds") List<Long> loanIds, @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID)
|
||||
List<Long> findAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(@Param("minLoanId") Long minLoanId,
|
||||
@Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate);
|
||||
@Query(FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES)
|
||||
List<Long> findAllLoansByLastClosedBusinessDateAndMinAndMaxLoanIdAndStatuses(@Param("minLoanId") Long minLoanId,
|
||||
@Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID)
|
||||
List<Long> findAllNonClosedLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanId(@Param("minLoanId") Long minLoanId,
|
||||
@Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate);
|
||||
@Query(FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES)
|
||||
List<Long> findAllLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanIdAndStatuses(@Param("minLoanId") Long minLoanId,
|
||||
@Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_OLDEST_COB_PROCESSED_LOAN)
|
||||
List<LoanIdAndLastClosedBusinessDate> findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate);
|
||||
List<LoanIdAndLastClosedBusinessDate> findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
@Query(FIND_ALL_STAYED_LOCKED_BY_COB_BUSINESS_DATE)
|
||||
List<LoanIdAndExternalIdAndAccountNo> findAllStayedLockedByCobBusinessDate(@Param("cobBusinessDate") LocalDate cobBusinessDate);
|
||||
|
||||
@Query(FIND_ALL_LOAN_IDS_BY_STATUS_ID)
|
||||
List<Long> findLoanIdByStatusId(@Param("statusId") Integer statusId);
|
||||
@Query(FIND_ALL_LOAN_IDS_BY_STATUS)
|
||||
List<Long> findLoanIdByStatus(@Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
@Query(FIND_LOANS_FOR_PERIODIC_ACCRUAL)
|
||||
List<Loan> findLoansForPeriodicAccrual(@Param("accountingType") Integer accountingType, @Param("tillDate") LocalDate tillDate,
|
||||
@Param("futureCharges") boolean futureCharges);
|
||||
List<Loan> findLoansForPeriodicAccrual(@Param("accountingType") AccountingRuleType accountingType,
|
||||
@Param("tillDate") LocalDate tillDate, @Param("futureCharges") boolean futureCharges,
|
||||
@Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
@Query(FIND_LOANS_FOR_ADD_ACCRUAL)
|
||||
List<Loan> findLoansForAddAccrual(@Param("accountingType") Integer accountingType, @Param("tillDate") LocalDate tillDate,
|
||||
@Param("futureCharges") boolean futureCharges);
|
||||
List<Loan> findLoansForAddAccrual(@Param("accountingType") AccountingRuleType accountingType, @Param("tillDate") LocalDate tillDate,
|
||||
@Param("futureCharges") boolean futureCharges, @Param("loanStatus") LoanStatus loanStatus);
|
||||
|
||||
@Query(FIND_LOAN_BY_EXTERNAL_ID)
|
||||
Optional<Loan> findByExternalId(@Param("externalId") ExternalId externalId);
|
||||
|
||||
+38
-21
@@ -25,8 +25,10 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -41,6 +43,13 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@RequiredArgsConstructor
|
||||
public class LoanRepositoryWrapper {
|
||||
|
||||
private static final Collection<LoanStatus> NON_CLOSED_LOAN_STATUSES = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE,
|
||||
LoanStatus.TRANSFER_IN_PROGRESS, LoanStatus.TRANSFER_ON_HOLD));
|
||||
private static final Collection<LoanStatus> NON_CLOSED_AND_OVERPAID_LOAN_STATUSES = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE,
|
||||
LoanStatus.TRANSFER_IN_PROGRESS, LoanStatus.TRANSFER_ON_HOLD, LoanStatus.OVERPAID));
|
||||
|
||||
private final LoanRepository repository;
|
||||
private final FineractProperties fineractProperties;
|
||||
|
||||
@@ -74,8 +83,8 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Root Entities are enough
|
||||
public Collection<Loan> findActiveLoansByLoanIdAndGroupId(Long clientId, Long groupId) {
|
||||
final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
|
||||
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue(), LoanStatus.OVERPAID.getValue()));
|
||||
final Collection<LoanStatus> loanStatuses = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE, LoanStatus.OVERPAID));
|
||||
return this.repository.findByClientIdAndGroupIdAndLoanStatus(clientId, groupId, loanStatuses);
|
||||
}
|
||||
|
||||
@@ -102,7 +111,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Only root entities is enough
|
||||
public List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId,
|
||||
@Param("loanType") Integer loanType) {
|
||||
@Param("loanType") AccountType loanType) {
|
||||
return this.repository.getGroupLoansDisbursedAfter(disbursementDate, groupId, loanType);
|
||||
}
|
||||
|
||||
@@ -112,12 +121,12 @@ public class LoanRepositoryWrapper {
|
||||
return this.repository.getClientOrJLGLoansDisbursedAfter(disbursementDate, clientId);
|
||||
}
|
||||
|
||||
public Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") Integer loanType) {
|
||||
public Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") AccountType loanType) {
|
||||
return this.repository.getMaxGroupLoanCounter(groupId, loanType);
|
||||
}
|
||||
|
||||
public Integer getMaxGroupLoanProductCounter(@Param("productId") Long productId, @Param("groupId") Long groupId,
|
||||
@Param("loanType") Integer loanType) {
|
||||
@Param("loanType") AccountType loanType) {
|
||||
return this.repository.getMaxGroupLoanProductCounter(productId, groupId, loanType);
|
||||
}
|
||||
|
||||
@@ -140,7 +149,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Only root entities are enough
|
||||
public List<Loan> getGroupLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("groupId") Long groupId,
|
||||
@Param("groupLoanType") Integer groupLoanType) {
|
||||
@Param("groupLoanType") AccountType groupLoanType) {
|
||||
return this.repository.getGroupLoansToUpdateLoanCounter(loanCounter, groupId, groupLoanType);
|
||||
}
|
||||
|
||||
@@ -151,7 +160,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Only root entities are enough
|
||||
public List<Loan> getGroupLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter,
|
||||
@Param("groupId") Long groupId, @Param("groupLoanType") Integer groupLoanType) {
|
||||
@Param("groupId") Long groupId, @Param("groupLoanType") AccountType groupLoanType) {
|
||||
return this.repository.getGroupLoansToUpdateLoanProductCounter(loanProductCounter, groupId, groupLoanType);
|
||||
}
|
||||
|
||||
@@ -193,7 +202,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Looks like we need complete Data
|
||||
public List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes) {
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses, @Param("loanTypes") Collection<AccountType> loanTypes) {
|
||||
List<Loan> loans = new ArrayList<>();
|
||||
List<List<Long>> partitions = Lists.partition(ids.stream().toList(), fineractProperties.getQuery().getInClauseParameterSizeLimit());
|
||||
partitions
|
||||
@@ -213,7 +222,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Repayments Schedule
|
||||
public List<Loan> findByClientOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses) {
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses) {
|
||||
List<Loan> loans = this.repository.findByClientOfficeIdsAndLoanStatus(officeIds, loanStatuses);
|
||||
if (loans != null && loans.size() > 0) {
|
||||
for (Loan loan : loans) {
|
||||
@@ -225,7 +234,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
// Repayments Schedule
|
||||
public List<Loan> findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
|
||||
@Param("loanStatuses") Collection<Integer> loanStatuses) {
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses) {
|
||||
List<Loan> loans = this.repository.findByGroupOfficeIdsAndLoanStatus(officeIds, loanStatuses);
|
||||
if (loans != null && loans.size() > 0) {
|
||||
for (Loan loan : loans) {
|
||||
@@ -235,34 +244,42 @@ public class LoanRepositoryWrapper {
|
||||
return loans;
|
||||
}
|
||||
|
||||
public List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus) {
|
||||
public List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") LoanStatus loanStatus) {
|
||||
return this.repository.findActiveLoansLoanProductIdsByClient(clientId, loanStatus);
|
||||
}
|
||||
|
||||
public List<Long> findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus) {
|
||||
public List<Long> findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") LoanStatus loanStatus) {
|
||||
return this.repository.findActiveLoansLoanProductIdsByGroup(groupId, loanStatus);
|
||||
}
|
||||
|
||||
public boolean doNonClosedLoanAccountsExistForClient(@Param("clientId") Long clientId) {
|
||||
return this.repository.doNonClosedLoanAccountsExistForClient(clientId);
|
||||
return this.repository.doLoanAccountsWithLoansInStatusesExistForClient(clientId, NON_CLOSED_AND_OVERPAID_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
public boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long productId) {
|
||||
return this.repository.doNonClosedLoanAccountsExistForProduct(productId);
|
||||
return this.repository.doLoanAccountsWithLoansInStatusesExistForProduct(productId, NON_CLOSED_AND_OVERPAID_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
public Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String accountNumber) {
|
||||
return this.repository.findNonClosedLoanByAccountNumber(accountNumber);
|
||||
return this.repository.findLoanByAccountNumberAndStatuses(accountNumber, NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
public boolean existsNonClosedLoanByExternalLoanId(final ExternalId externalId) {
|
||||
return this.repository.existsLoanByExternalLoanIdAndStatuses(externalId, NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
public boolean existLoanByExternalId(final ExternalId externalId) {
|
||||
return this.repository.existsByExternalId(externalId);
|
||||
}
|
||||
|
||||
public List<Long> findAllNonClosedLoanIds() {
|
||||
return this.repository.findAllLoanIdsByStatuses(NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
// Looks like we need complete entity
|
||||
@Transactional(readOnly = true)
|
||||
public Loan findNonClosedLoanThatBelongsToClient(@Param("loanId") Long loanId, @Param("clientId") Long clientId) {
|
||||
Loan loan = this.repository.findNonClosedLoanThatBelongsToClient(loanId, clientId);
|
||||
Loan loan = this.repository.findLoanByClientAndStatus(loanId, clientId, LoanStatus.ACTIVE);
|
||||
if (loan != null) {
|
||||
loan.initializeTransactions();
|
||||
}
|
||||
@@ -274,15 +291,15 @@ public class LoanRepositoryWrapper {
|
||||
}
|
||||
|
||||
public List<Long> findLoanIdsByStatusId(Integer statusId) {
|
||||
return repository.findLoanIdByStatusId(statusId);
|
||||
return repository.findLoanIdByStatus(LoanStatus.fromInt(statusId));
|
||||
}
|
||||
|
||||
public List<Loan> findLoansForPeriodicAccrual(Integer accountingType, LocalDate tillDate, boolean futureCharges) {
|
||||
return repository.findLoansForPeriodicAccrual(accountingType, tillDate, futureCharges);
|
||||
public List<Loan> findLoansForPeriodicAccrual(AccountingRuleType accountingType, LocalDate tillDate, boolean futureCharges) {
|
||||
return repository.findLoansForPeriodicAccrual(accountingType, tillDate, futureCharges, LoanStatus.ACTIVE);
|
||||
}
|
||||
|
||||
public List<Loan> findLoansForAddAccrual(Integer accountingType, LocalDate tillDate, boolean futureCharges) {
|
||||
return repository.findLoansForAddAccrual(accountingType, tillDate, futureCharges);
|
||||
public List<Loan> findLoansForAddAccrual(AccountingRuleType accountingType, LocalDate tillDate, boolean futureCharges) {
|
||||
return repository.findLoansForAddAccrual(accountingType, tillDate, futureCharges, LoanStatus.ACTIVE);
|
||||
}
|
||||
|
||||
public List<Long> findIdByExternalIds(List<ExternalId> externalIds) {
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class LoanStatusConverter implements AttributeConverter<LoanStatus, Integer> {
|
||||
|
||||
@Override
|
||||
public Integer convertToDatabaseColumn(LoanStatus attribute) {
|
||||
return attribute == null ? null : attribute.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanStatus convertToEntityAttribute(Integer dbData) {
|
||||
return LoanStatus.fromInt(dbData);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class LoanSubStatusConverter implements AttributeConverter<LoanSubStatus, Integer> {
|
||||
|
||||
@Override
|
||||
public Integer convertToDatabaseColumn(LoanSubStatus attribute) {
|
||||
return attribute == null ? null : attribute.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanSubStatus convertToEntityAttribute(Integer dbData) {
|
||||
return dbData == null ? null : LoanSubStatus.fromInt(dbData);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class LoanSummaryBalancesRepository {
|
||||
private final CriteriaQueryFactory criteriaQueryFactory;
|
||||
|
||||
public Collection<LoanTransactionBalance> retrieveLoanSummaryBalancesByTransactionType(final Long loanId,
|
||||
final List<Integer> transactionTypes) {
|
||||
final List<LoanTransactionType> transactionTypes) {
|
||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<LoanTransactionBalance> query = cb.createQuery(LoanTransactionBalance.class);
|
||||
|
||||
|
||||
+23
-24
@@ -75,7 +75,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
private PaymentDetail paymentDetail;
|
||||
|
||||
@Column(name = "transaction_type_enum", nullable = false)
|
||||
private Integer typeOf;
|
||||
private LoanTransactionType typeOf;
|
||||
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
private LocalDate dateOf;
|
||||
@@ -145,13 +145,12 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
public static LoanTransaction incomePosting(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final ExternalId externalId) {
|
||||
final Integer typeOf = LoanTransactionType.INCOME_POSTING.getValue();
|
||||
final BigDecimal principalPortion = BigDecimal.ZERO;
|
||||
final BigDecimal overPaymentPortion = BigDecimal.ZERO;
|
||||
final boolean reversed = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
return new LoanTransaction(loan, office, typeOf, dateOf, amount, principalPortion, interestPortion, feeChargesPortion,
|
||||
penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INCOME_POSTING, dateOf, amount, principalPortion, interestPortion,
|
||||
feeChargesPortion, penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction disbursement(final Loan loan, final Money amount, final PaymentDetail paymentDetail,
|
||||
@@ -263,19 +262,19 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
public static LoanTransaction accrueTransaction(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(), dateOf, amount, null, interestPortion,
|
||||
feeChargesPortion, penaltyChargesPortion, null, false, null, externalId);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL, dateOf, amount, null, interestPortion, feeChargesPortion,
|
||||
penaltyChargesPortion, null, false, null, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction accrualAdjustment(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feePortion, final BigDecimal penaltyPortion, final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL_ADJUSTMENT.getValue(), dateOf, amount, null, interestPortion,
|
||||
feePortion, penaltyPortion, null, false, null, externalId);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL_ADJUSTMENT, dateOf, amount, null, interestPortion, feePortion,
|
||||
penaltyPortion, null, false, null, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER.getValue(), transferDate,
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER, transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
|
||||
@@ -283,7 +282,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
|
||||
public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate,
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER, transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
|
||||
@@ -291,7 +290,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
|
||||
public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate,
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER, transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
|
||||
@@ -326,8 +325,8 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
|
||||
public static LoanTransaction creditBalanceRefund(final Loan loan, final Office office, final Money amount, final LocalDate paymentDate,
|
||||
final ExternalId externalId, PaymentDetail paymentDetail) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND.getValue(), paymentDate, amount.getAmount(),
|
||||
null, null, null, null, amount.getAmount(), false, paymentDetail, externalId);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND, paymentDate, amount.getAmount(), null, null,
|
||||
null, null, amount.getAmount(), false, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction refundForActiveLoan(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
@@ -339,8 +338,8 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
public static LoanTransaction interestRefund(final Loan loan, final Office office, final BigDecimal amount, final BigDecimal principal,
|
||||
final BigDecimal interest, final BigDecimal feeCharges, final BigDecimal penaltyCharges, final PaymentDetail paymentDetail,
|
||||
final LocalDate refundDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INTEREST_REFUND.getValue(), refundDate, amount, principal, interest,
|
||||
feeCharges, penaltyCharges, amount, false, paymentDetail, externalId);
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INTEREST_REFUND, refundDate, amount, principal, interest, feeCharges,
|
||||
penaltyCharges, amount, false, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static boolean transactionAmountsMatch(final MonetaryCurrency currency, final LoanTransaction loanTransaction,
|
||||
@@ -353,10 +352,10 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
&& loanTransaction.getOverPaymentPortion(currency).isEqualTo(newLoanTransaction.getOverPaymentPortion(currency));
|
||||
}
|
||||
|
||||
public LoanTransaction(final Loan loan, final Office office, final Integer typeOf, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
|
||||
final BigDecimal penaltyChargesPortion, final BigDecimal overPaymentPortion, final boolean reversed,
|
||||
final PaymentDetail paymentDetail, final ExternalId externalId) {
|
||||
public LoanTransaction(final Loan loan, final Office office, final LoanTransactionType typeOf, final LocalDate dateOf,
|
||||
final BigDecimal amount, final BigDecimal principalPortion, final BigDecimal interestPortion,
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overPaymentPortion,
|
||||
final boolean reversed, final PaymentDetail paymentDetail, final ExternalId externalId) {
|
||||
|
||||
this.loan = loan;
|
||||
this.typeOf = typeOf;
|
||||
@@ -403,14 +402,14 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
: null;
|
||||
BigDecimal totalOutstanding = loan.getSummary().getTotalOutstanding();
|
||||
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_OFF.getValue(), chargeOffDate, totalOutstanding,
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_OFF, chargeOffDate, totalOutstanding,
|
||||
principalPortion, interestPortion, feePortion, penaltyPortion, null, false, null, externalId);
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final BigDecimal amount,
|
||||
final LocalDate date, final ExternalId externalId) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.typeOf = type;
|
||||
this.amount = amount;
|
||||
this.dateOf = date;
|
||||
this.externalId = externalId;
|
||||
@@ -421,7 +420,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
|
||||
final BigDecimal amount, final LocalDate date, final ExternalId externalId) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.typeOf = type;
|
||||
this.paymentDetail = paymentDetail;
|
||||
this.amount = amount;
|
||||
this.dateOf = date;
|
||||
@@ -433,7 +432,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
|
||||
final BigDecimal amount, final LocalDate date, final ExternalId externalId, final String chargeRefundChargeType) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.typeOf = type;
|
||||
this.paymentDetail = paymentDetail;
|
||||
this.amount = amount;
|
||||
this.dateOf = date;
|
||||
@@ -552,7 +551,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
}
|
||||
|
||||
public LoanTransactionType getTypeOf() {
|
||||
return LoanTransactionType.fromInt(this.typeOf);
|
||||
return this.typeOf == null ? LoanTransactionType.INVALID : this.typeOf;
|
||||
}
|
||||
|
||||
public boolean isReversed() {
|
||||
|
||||
+2
-2
@@ -49,8 +49,8 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
||||
lt.loan.loanProduct.delinquencyBucket is not null
|
||||
GROUP BY lt.loan
|
||||
""")
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanTransactionsByTypeAndLessOrEqualDate(@Param("transactionType") Integer transactionType,
|
||||
@Param("businessDate") LocalDate businessDate);
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanTransactionsByTypeAndLessOrEqualDate(
|
||||
@Param("transactionType") LoanTransactionType transactionType, @Param("businessDate") LocalDate businessDate);
|
||||
|
||||
@Query(FIND_ID_BY_EXTERNAL_ID)
|
||||
Long findIdByExternalId(@Param("externalId") ExternalId externalId);
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class LoanTransactionTypeConverter implements AttributeConverter<LoanTransactionType, Integer> {
|
||||
|
||||
@Override
|
||||
public Integer convertToDatabaseColumn(LoanTransactionType attribute) {
|
||||
return attribute == null ? null : attribute.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanTransactionType convertToEntityAttribute(Integer dbData) {
|
||||
return dbData == null ? null : LoanTransactionType.fromInt(dbData);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -62,7 +62,7 @@ public class SetLoanDelinquencyTagsTasklet implements Tasklet {
|
||||
|
||||
// Read Loan Ids with Loan Transaction Charge back
|
||||
Collection<LoanScheduleDelinquencyData> loanScheduleDelinquencyData = this.loanTransactionRepository
|
||||
.fetchLoanTransactionsByTypeAndLessOrEqualDate(LoanTransactionType.CHARGEBACK.getValue(), businessDate);
|
||||
.fetchLoanTransactionsByTypeAndLessOrEqualDate(LoanTransactionType.CHARGEBACK, businessDate);
|
||||
List<Long> processedLoans = applyDelinquencyTagToLoans(loanScheduleDelinquencyData);
|
||||
log.debug("{}: Records affected by setLoanDelinquencyTags: {}", ThreadLocalContextUtil.getTenant().getName(),
|
||||
processedLoans.size());
|
||||
@@ -70,10 +70,10 @@ public class SetLoanDelinquencyTagsTasklet implements Tasklet {
|
||||
// Read Loan Ids with overdue installments
|
||||
if (processedLoans.isEmpty()) {
|
||||
loanScheduleDelinquencyData = this.loanRepaymentScheduleInstallmentRepository
|
||||
.fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE.getValue(), businessDate, false);
|
||||
.fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE, businessDate, false);
|
||||
} else {
|
||||
loanScheduleDelinquencyData = this.loanRepaymentScheduleInstallmentRepository
|
||||
.fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE.getValue(), businessDate, false, processedLoans);
|
||||
.fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE, businessDate, false, processedLoans);
|
||||
}
|
||||
applyDelinquencyTagToLoans(loanScheduleDelinquencyData);
|
||||
|
||||
|
||||
+2
-2
@@ -153,7 +153,7 @@ public final class LoanApplicationTransitionValidator {
|
||||
// validate loan state transition
|
||||
|
||||
final LoanStatus statusEnum = defaultLoanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_REJECTED, loan);
|
||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(loan.getLoanStatus()))) {
|
||||
if (!statusEnum.hasStateOf(loan.getLoanStatus())) {
|
||||
final LocalDate rejectedOn = command.localDateValueOfParameterNamed(Loan.REJECTED_ON_DATE);
|
||||
if (DateUtils.isBefore(rejectedOn, loan.getSubmittedOnDate())) {
|
||||
final String errorMessage = "The date on which a loan is rejected cannot be before its submittal date: "
|
||||
@@ -214,7 +214,7 @@ public final class LoanApplicationTransitionValidator {
|
||||
|
||||
// validate loan state transition
|
||||
final LoanStatus statusEnum = defaultLoanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_WITHDRAWN, loan);
|
||||
if (!statusEnum.hasStateOf(LoanStatus.fromInt(loan.getLoanStatus()))) {
|
||||
if (!statusEnum.hasStateOf(loan.getLoanStatus())) {
|
||||
LocalDate withdrawnOn = command.localDateValueOfParameterNamed(Loan.WITHDRAWN_ON_DATE);
|
||||
if (withdrawnOn == null) {
|
||||
withdrawnOn = command.localDateValueOfParameterNamed(Loan.EVENT_DATE);
|
||||
|
||||
+5
-3
@@ -32,6 +32,7 @@ import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -42,14 +43,15 @@ public class LoanTransactionReadService {
|
||||
|
||||
private final EntityManager entityManager;
|
||||
|
||||
public List<LoanTransaction> fetchLoanTransactionsByType(final Long loanId, final String externalId, final Integer transactionType) {
|
||||
final List<Integer> transactionTypes = new ArrayList<>();
|
||||
public List<LoanTransaction> fetchLoanTransactionsByType(final Long loanId, final String externalId,
|
||||
final LoanTransactionType transactionType) {
|
||||
final List<LoanTransactionType> transactionTypes = new ArrayList<>();
|
||||
transactionTypes.add(transactionType);
|
||||
return fetchLoanTransactionsByTypes(loanId, externalId, transactionTypes);
|
||||
}
|
||||
|
||||
public List<LoanTransaction> fetchLoanTransactionsByTypes(final Long loanId, final String externalId,
|
||||
final List<Integer> transactionTypes) {
|
||||
final List<LoanTransactionType> transactionTypes) {
|
||||
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<LoanTransaction> query = cb.createQuery(LoanTransaction.class);
|
||||
|
||||
+9
-10
@@ -132,7 +132,7 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
||||
private LoanProductMinMaxConstraints loanProductMinMaxConstraints;
|
||||
|
||||
@Column(name = "accounting_type", nullable = false)
|
||||
private Integer accountingRule;
|
||||
private AccountingRuleType accountingRule;
|
||||
|
||||
@Column(name = "include_in_borrower_cycle")
|
||||
private boolean includeInBorrowerCycle;
|
||||
@@ -767,9 +767,7 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
||||
defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments,
|
||||
defaultMaxNumberOfInstallments);
|
||||
|
||||
if (accountingRuleType != null) {
|
||||
this.accountingRule = accountingRuleType.getValue();
|
||||
}
|
||||
this.accountingRule = accountingRuleType;
|
||||
this.includeInBorrowerCycle = includeInBorrowerCycle;
|
||||
this.useBorrowerCycle = useBorrowerCycle;
|
||||
|
||||
@@ -994,10 +992,11 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
||||
}
|
||||
|
||||
final String accountingTypeParamName = "accountingRule";
|
||||
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingRule)) {
|
||||
Integer currentValue = this.accountingRule == null ? null : this.accountingRule.getValue();
|
||||
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, currentValue)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(accountingTypeParamName);
|
||||
actualChanges.put(accountingTypeParamName, newValue);
|
||||
this.accountingRule = newValue;
|
||||
this.accountingRule = AccountingRuleType.fromInt(newValue);
|
||||
}
|
||||
|
||||
final String nameParamName = "name";
|
||||
@@ -1414,19 +1413,19 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
||||
}
|
||||
|
||||
public boolean isAccountingDisabled() {
|
||||
return AccountingRuleType.NONE.getValue().equals(this.accountingRule);
|
||||
return AccountingRuleType.NONE.equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public boolean isCashBasedAccountingEnabled() {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule);
|
||||
return AccountingRuleType.CASH_BASED.equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public boolean isUpfrontAccrualAccountingEnabled() {
|
||||
return AccountingRuleType.ACCRUAL_UPFRONT.getValue().equals(this.accountingRule);
|
||||
return AccountingRuleType.ACCRUAL_UPFRONT.equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public boolean isPeriodicAccrualAccountingEnabled() {
|
||||
return AccountingRuleType.ACCRUAL_PERIODIC.getValue().equals(this.accountingRule);
|
||||
return AccountingRuleType.ACCRUAL_PERIODIC.equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public Money getPrincipalAmount() {
|
||||
|
||||
+1
-2
@@ -357,13 +357,12 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
@Override
|
||||
@Transactional
|
||||
public Map<String, Object> updateLoanProductToGLAccountMapping(final Long loanProductId, final JsonCommand command,
|
||||
final boolean accountingRuleChanged, final int accountingRuleTypeId) {
|
||||
final boolean accountingRuleChanged, final AccountingRuleType accountingRuleType) {
|
||||
/***
|
||||
* Variable tracks all accounting mapping properties that have been updated
|
||||
***/
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(command.json());
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId);
|
||||
|
||||
/***
|
||||
* If the accounting rule has been changed, delete all existing mapping for the product and recreate a new set
|
||||
|
||||
+19
-9
@@ -21,6 +21,9 @@ package org.apache.fineract.cob.loan;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.cob.data.LoanCOBParameter;
|
||||
@@ -30,12 +33,17 @@ import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
|
||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class RetrieveAllNonClosedLoanIdServiceImpl implements RetrieveLoanIdService {
|
||||
|
||||
private static final Collection<LoanStatus> NON_CLOSED_LOAN_STATUSES = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE,
|
||||
LoanStatus.TRANSFER_IN_PROGRESS, LoanStatus.TRANSFER_ON_HOLD));
|
||||
|
||||
private final LoanRepository loanRepository;
|
||||
|
||||
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
@@ -69,30 +77,32 @@ public class RetrieveAllNonClosedLoanIdServiceImpl implements RetrieveLoanIdServ
|
||||
|
||||
@Override
|
||||
public List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsBehindDate(LocalDate businessDate, List<Long> loanIds) {
|
||||
return loanRepository.findAllNonClosedLoansBehindByLoanIds(businessDate, loanIds);
|
||||
return loanRepository.findAllLoansBehindByLoanIdsAndStatuses(businessDate, loanIds, NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsBehindDateOrNull(LocalDate businessDate, List<Long> loanIds) {
|
||||
return loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(businessDate, loanIds);
|
||||
return loanRepository.findAllLoansBehindOrNullByLoanIdsAndStatuses(businessDate, loanIds, NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsOldestCobProcessed(LocalDate businessDate) {
|
||||
return loanRepository.findOldestCOBProcessedLoan(businessDate);
|
||||
return loanRepository.findOldestCOBProcessedLoan(businessDate, NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(LoanCOBParameter loanCOBParameter,
|
||||
boolean isCatchUp) {
|
||||
if (isCatchUp) {
|
||||
return loanRepository.findAllNonClosedLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanId(loanCOBParameter.getMinLoanId(),
|
||||
loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)
|
||||
.minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND));
|
||||
return loanRepository.findAllLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanIdAndStatuses(
|
||||
loanCOBParameter.getMinLoanId(), loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil
|
||||
.getBusinessDateByType(BusinessDateType.COB_DATE).minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND),
|
||||
NON_CLOSED_LOAN_STATUSES);
|
||||
} else {
|
||||
return loanRepository.findAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter.getMinLoanId(),
|
||||
loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)
|
||||
.minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND));
|
||||
return loanRepository.findAllLoansByLastClosedBusinessDateAndMinAndMaxLoanIdAndStatuses(
|
||||
loanCOBParameter.getMinLoanId(), loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil
|
||||
.getBusinessDateByType(BusinessDateType.COB_DATE).minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND),
|
||||
NON_CLOSED_LOAN_STATUSES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -89,7 +89,7 @@ import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.account.exception.DifferentCurrenciesException;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.apache.fineract.portfolio.note.domain.Note;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
@@ -128,7 +128,7 @@ public class InteropServiceImpl implements InteropService {
|
||||
private final NoteRepository noteRepository;
|
||||
private final PaymentTypeRepository paymentTypeRepository;
|
||||
private final InteropIdentifierRepository identifierRepository;
|
||||
private final LoanRepository loanRepository;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
|
||||
private final SavingsHelper savingsHelper;
|
||||
private final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper;
|
||||
@@ -556,7 +556,7 @@ public class InteropServiceImpl implements InteropService {
|
||||
}
|
||||
|
||||
private Loan validateAndGetLoan(String accountId) {
|
||||
Loan loan = loanRepository.findNonClosedLoanByAccountNumber(accountId);
|
||||
Loan loan = loanRepositoryWrapper.findNonClosedLoanByAccountNumber(accountId);
|
||||
if (loan == null) {
|
||||
throw new LoanNotFoundException(accountId);
|
||||
}
|
||||
|
||||
+7
-6
@@ -28,7 +28,7 @@ import org.apache.fineract.interoperation.service.InteropService;
|
||||
import org.apache.fineract.interoperation.service.InteropServiceImpl;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
|
||||
@@ -49,14 +49,15 @@ public class InteroperationConfiguration {
|
||||
public InteropService interopService(PlatformSecurityContext securityContext, InteropDataValidator interopDataValidator,
|
||||
SavingsAccountRepository savingsAccountRepository, SavingsAccountTransactionRepository savingsAccountTransactionRepository,
|
||||
ApplicationCurrencyRepository applicationCurrencyRepository, NoteRepository noteRepository,
|
||||
PaymentTypeRepository paymentTypeRepository, InteropIdentifierRepository identifierRepository, LoanRepository loanRepository,
|
||||
SavingsHelper savingsHelper, SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
|
||||
PaymentTypeRepository paymentTypeRepository, InteropIdentifierRepository identifierRepository,
|
||||
LoanRepositoryWrapper loanRepositoryWrapper, SavingsHelper savingsHelper,
|
||||
SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
|
||||
SavingsAccountDomainService savingsAccountService, JdbcTemplate jdbcTemplate,
|
||||
PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer, DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
return new InteropServiceImpl(securityContext, interopDataValidator, savingsAccountRepository, savingsAccountTransactionRepository,
|
||||
applicationCurrencyRepository, noteRepository, paymentTypeRepository, identifierRepository, loanRepository, savingsHelper,
|
||||
savingsAccountTransactionSummaryWrapper, savingsAccountService, jdbcTemplate, commandsSourceWritePlatformService,
|
||||
toApiJsonSerializer, sqlGenerator);
|
||||
applicationCurrencyRepository, noteRepository, paymentTypeRepository, identifierRepository, loanRepositoryWrapper,
|
||||
savingsHelper, savingsAccountTransactionSummaryWrapper, savingsAccountService, jdbcTemplate,
|
||||
commandsSourceWritePlatformService, toApiJsonSerializer, sqlGenerator);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
@@ -52,15 +53,16 @@ public interface CalendarInstanceRepository extends JpaRepository<CalendarInstan
|
||||
Collection<CalendarInstance> findByCalendarIdAndEntityTypeId(Long calendarId, Integer entityTypeId);
|
||||
|
||||
/** Should use in clause, can I do it without creating a new class? **/
|
||||
@Query("select ci from CalendarInstance ci where ci.entityId in (select loan.id from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and (loan.loanStatus = 100 or loan.loanStatus = 200 or loan.loanStatus = 300)) and ci.entityTypeId = 3")
|
||||
List<CalendarInstance> findCalendarInstancesForActiveLoansByGroupIdAndClientId(@Param("groupId") Long groupId,
|
||||
@Param("clientId") Long clientId);
|
||||
@Query("select ci from CalendarInstance ci where ci.entityId in (select loan.id from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and loan.loanStatus in :loanStatuses) and ci.entityTypeId = 3")
|
||||
List<CalendarInstance> findCalendarInstancesForLoansByGroupIdAndClientIdAndStatuses(@Param("groupId") Long groupId,
|
||||
@Param("clientId") Long clientId, @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
/**
|
||||
* EntityType = 3 is for loan
|
||||
*/
|
||||
|
||||
@Query("SELECT COUNT(ci.id) FROM CalendarInstance ci, Loan loan WHERE loan.id = ci.entityId AND ci.entityTypeId = 3 AND ci.calendar.id = :calendarId AND loan.loanStatus IN :loanStatuses ")
|
||||
Integer countOfLoansSyncedWithCalendar(@Param("calendarId") Long calendarId, @Param("loanStatuses") Collection<Integer> loanStatuses);
|
||||
Integer countOfLoansSyncedWithCalendar(@Param("calendarId") Long calendarId,
|
||||
@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -196,8 +196,8 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
|
||||
Boolean areActiveEntitiesSynced = false;
|
||||
final Long calendarId = command.entityId();
|
||||
|
||||
final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
|
||||
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
|
||||
final Collection<LoanStatus> loanStatuses = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
|
||||
|
||||
final Integer numberOfActiveLoansSyncedWithThisCalendar = this.calendarInstanceRepository.countOfLoansSyncedWithCalendar(calendarId,
|
||||
loanStatuses);
|
||||
|
||||
+1
-1
@@ -1065,7 +1065,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
|
||||
private void handleForeClosureTransactions(final Loan loan, final LoanTransaction repaymentTransaction,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
loan.setLoanSubStatus(LoanSubStatus.FORECLOSED.getValue());
|
||||
loan.setLoanSubStatus(LoanSubStatus.FORECLOSED);
|
||||
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction, loanLifecycleStateMachine,
|
||||
null, scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
+4
-1
@@ -27,6 +27,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccrualActivityRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualActivityProcessingService;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
@@ -46,7 +48,8 @@ public class AccrualActivityPostingTasklet implements Tasklet {
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
final LocalDate yesterday = DateUtils.getBusinessLocalDate().minusDays(1);
|
||||
List<Throwable> errors = new ArrayList<>();
|
||||
Set<Long> loanAccounts = loanAccrualActivityRepository.fetchLoanIdsForAccrualActivityPosting(yesterday);
|
||||
Set<Long> loanAccounts = loanAccrualActivityRepository.fetchLoanIdsForAccrualActivityPosting(yesterday,
|
||||
LoanTransactionType.ACCRUAL_ACTIVITY, LoanStatus.ACTIVE);
|
||||
for (Long accountId : loanAccounts) {
|
||||
try {
|
||||
loanAccrualActivityProcessingService.makeAccrualActivityTransaction(accountId, yesterday);
|
||||
|
||||
+2
-2
@@ -68,8 +68,8 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
|
||||
final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
|
||||
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
|
||||
final Collection<LoanStatus> loanStatuses = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
|
||||
final List<Holiday> holidays = holidayRepository.findUnprocessed();
|
||||
|
||||
for (final Holiday holiday : holidays) {
|
||||
|
||||
+4
-6
@@ -210,7 +210,7 @@ public final class LoanApplicationValidator {
|
||||
expectedFirstRepaymentOnDate);
|
||||
}
|
||||
|
||||
validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType(),
|
||||
validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType().getValue(),
|
||||
loan.repaymentScheduleDetail().getNumberOfRepayments(), loan.repaymentScheduleDetail().getRepayEvery(),
|
||||
loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue(), loan);
|
||||
}
|
||||
@@ -224,7 +224,7 @@ public final class LoanApplicationValidator {
|
||||
expectedFirstRepaymentOnDate);
|
||||
}
|
||||
|
||||
validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType(),
|
||||
validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType().getValue(),
|
||||
loan.repaymentScheduleDetail().getNumberOfRepayments(), loan.repaymentScheduleDetail().getRepayEvery(),
|
||||
loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue(), loan);
|
||||
}
|
||||
@@ -1850,11 +1850,9 @@ public final class LoanApplicationValidator {
|
||||
final Long clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element);
|
||||
|
||||
if (groupId != null) {
|
||||
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByGroup(groupId,
|
||||
LoanStatus.ACTIVE.getValue());
|
||||
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByGroup(groupId, LoanStatus.ACTIVE);
|
||||
} else {
|
||||
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByClient(clientId,
|
||||
LoanStatus.ACTIVE.getValue());
|
||||
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByClient(clientId, LoanStatus.ACTIVE);
|
||||
}
|
||||
checkForProductMixRestrictions(activeLoansLoanProductIds, productId);
|
||||
}
|
||||
|
||||
+18
-22
@@ -56,40 +56,36 @@ public abstract class CommonLoanSummaryDataProvider implements LoanSummaryDataPr
|
||||
BigDecimal totalUnpaidPayableDueInterest = BigDecimal.ZERO;
|
||||
BigDecimal totalUnpaidPayableNotDueInterest = BigDecimal.ZERO;
|
||||
|
||||
totalChargeAdjustment = fetchLoanTransactionBalanceByType(loanTransactionBalances,
|
||||
LoanTransactionType.CHARGE_ADJUSTMENT.getValue());
|
||||
totalChargeAdjustment = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGE_ADJUSTMENT);
|
||||
totalChargeAdjustmentReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.CHARGE_ADJUSTMENT.getValue());
|
||||
LoanTransactionType.CHARGE_ADJUSTMENT);
|
||||
|
||||
totalChargeback = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGEBACK.getValue());
|
||||
totalChargeback = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGEBACK);
|
||||
|
||||
totalCreditBalanceRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances,
|
||||
LoanTransactionType.CREDIT_BALANCE_REFUND.getValue());
|
||||
totalCreditBalanceRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CREDIT_BALANCE_REFUND);
|
||||
totalCreditBalanceRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.CREDIT_BALANCE_REFUND.getValue());
|
||||
LoanTransactionType.CREDIT_BALANCE_REFUND);
|
||||
|
||||
totalGoodwillCredit = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.GOODWILL_CREDIT.getValue());
|
||||
totalGoodwillCredit = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.GOODWILL_CREDIT);
|
||||
totalGoodwillCreditReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.GOODWILL_CREDIT.getValue());
|
||||
LoanTransactionType.GOODWILL_CREDIT);
|
||||
|
||||
totalInterestRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.INTEREST_REFUND.getValue());
|
||||
totalInterestRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.INTEREST_REFUND);
|
||||
|
||||
totalInterestPaymentWaiver = fetchLoanTransactionBalanceByType(loanTransactionBalances,
|
||||
LoanTransactionType.INTEREST_PAYMENT_WAIVER.getValue());
|
||||
LoanTransactionType.INTEREST_PAYMENT_WAIVER);
|
||||
|
||||
totalMerchantRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances,
|
||||
LoanTransactionType.MERCHANT_ISSUED_REFUND.getValue());
|
||||
totalMerchantRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.MERCHANT_ISSUED_REFUND);
|
||||
totalMerchantRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.MERCHANT_ISSUED_REFUND.getValue());
|
||||
LoanTransactionType.MERCHANT_ISSUED_REFUND);
|
||||
|
||||
totalPayoutRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.PAYOUT_REFUND.getValue());
|
||||
totalPayoutRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.PAYOUT_REFUND.getValue());
|
||||
totalPayoutRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.PAYOUT_REFUND);
|
||||
totalPayoutRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, LoanTransactionType.PAYOUT_REFUND);
|
||||
|
||||
totalRepaymentTransaction = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.REPAYMENT.getValue())
|
||||
.add(fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.DOWN_PAYMENT.getValue()));
|
||||
totalRepaymentTransaction = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.REPAYMENT)
|
||||
.add(fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.DOWN_PAYMENT));
|
||||
totalRepaymentTransactionReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.REPAYMENT.getValue());
|
||||
LoanTransactionType.REPAYMENT);
|
||||
|
||||
if (repaymentSchedule != null) {
|
||||
// Outstanding Interest on Past due installments
|
||||
@@ -142,14 +138,14 @@ public abstract class CommonLoanSummaryDataProvider implements LoanSummaryDataPr
|
||||
}
|
||||
|
||||
private static BigDecimal fetchLoanTransactionBalanceByType(final Collection<LoanTransactionBalance> loanTransactionBalances,
|
||||
final Integer transactionType) {
|
||||
final LoanTransactionType transactionType) {
|
||||
final Optional<LoanTransactionBalance> optLoanTransactionBalance = loanTransactionBalances.stream()
|
||||
.filter(balance -> balance.getTransactionType().equals(transactionType) && !balance.isReversed()).findFirst();
|
||||
return optLoanTransactionBalance.isPresent() ? optLoanTransactionBalance.get().getAmount() : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private static BigDecimal fetchLoanTransactionBalanceReversedByType(final Collection<LoanTransactionBalance> loanTransactionBalances,
|
||||
final Integer transactionType) {
|
||||
final LoanTransactionType transactionType) {
|
||||
final Optional<LoanTransactionBalance> optLoanTransactionBalance = loanTransactionBalances.stream()
|
||||
.filter(balance -> balance.getTransactionType().equals(transactionType) && balance.isReversed()
|
||||
&& balance.isManuallyAdjustedOrReversed())
|
||||
|
||||
+2
-2
@@ -147,8 +147,8 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
||||
if (MathUtil.isGreaterThanZero(feeChargesPortion) || MathUtil.isGreaterThanZero(penaltyChargesPortion)
|
||||
|| MathUtil.isGreaterThanZero(interestPortion)) {
|
||||
BigDecimal transactionAmount = MathUtil.add(feeChargesPortion, penaltyChargesPortion, interestPortion);
|
||||
LoanTransaction newActivity = new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY.getValue(),
|
||||
closureDate, transactionAmount, null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null,
|
||||
LoanTransaction newActivity = new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY, closureDate,
|
||||
transactionAmount, null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null,
|
||||
externalIdFactory.create());
|
||||
makeAccrualActivityTransaction(loan, newActivity);
|
||||
}
|
||||
|
||||
+2
-2
@@ -106,7 +106,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
@Override
|
||||
@Transactional
|
||||
public void addPeriodicAccruals(@NotNull LocalDate tillDate) throws JobExecutionException {
|
||||
List<Loan> loans = loanRepositoryWrapper.findLoansForPeriodicAccrual(AccountingRuleType.ACCRUAL_PERIODIC.getValue(), tillDate,
|
||||
List<Loan> loans = loanRepositoryWrapper.findLoansForPeriodicAccrual(AccountingRuleType.ACCRUAL_PERIODIC, tillDate,
|
||||
!isChargeOnDueDate());
|
||||
List<Throwable> errors = new ArrayList<>();
|
||||
for (Loan loan : loans) {
|
||||
@@ -141,7 +141,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
@Override
|
||||
@Transactional
|
||||
public void addAccruals(@NotNull LocalDate tillDate) throws JobExecutionException {
|
||||
List<Loan> loans = loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC.getValue(), tillDate,
|
||||
List<Loan> loans = loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC, tillDate,
|
||||
!isChargeOnDueDate());
|
||||
List<Throwable> errors = new ArrayList<>();
|
||||
for (Loan loan : loans) {
|
||||
|
||||
+3
-2
@@ -61,6 +61,7 @@ import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.fund.domain.Fund;
|
||||
import org.apache.fineract.portfolio.fund.domain.FundRepository;
|
||||
import org.apache.fineract.portfolio.fund.exception.FundNotFoundException;
|
||||
@@ -720,10 +721,10 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(LoanApiConstants.loanTermFrequencyTypeParameterName,
|
||||
loan.getTermPeriodFrequencyType())) {
|
||||
loan.getTermPeriodFrequencyType().getValue())) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(LoanApiConstants.loanTermFrequencyTypeParameterName);
|
||||
changes.put(LoanApiConstants.loanTermFrequencyTypeParameterName, newValue);
|
||||
loan.setTermPeriodFrequencyType(newValue);
|
||||
loan.setTermPeriodFrequencyType(PeriodFrequencyType.fromInt(newValue));
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.principalParameterName, loan.getApprovedPrincipal())) {
|
||||
|
||||
+2
-2
@@ -78,8 +78,8 @@ public class LoanTransactionAssembler {
|
||||
BigDecimal penaltyChargesPortion = installment.getPenaltyCharges();
|
||||
BigDecimal transactionAmount = MathUtil.add(interestPortion, feeChargesPortion, penaltyChargesPortion);
|
||||
return MathUtil.isGreaterThanZero(transactionAmount)
|
||||
? new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY.getValue(), transactionDate,
|
||||
transactionAmount, null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null, externalId)
|
||||
? new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY, transactionDate, transactionAmount,
|
||||
null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null, externalId)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-11
@@ -1003,7 +1003,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loan.setClosedOnDate(transactionDate);
|
||||
loan.setActualMaturityDate(transactionDate);
|
||||
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, loan);
|
||||
} else if (LoanStatus.fromInt(loan.getLoanStatus()).isOverpaid()) {
|
||||
} else if (loan.getLoanStatus().isOverpaid()) {
|
||||
if (loan.getTotalOverpaid() == null || BigDecimal.ZERO.compareTo(loan.getTotalOverpaid()) == 0) {
|
||||
loan.setOverpaidOnDate(null);
|
||||
}
|
||||
@@ -1306,8 +1306,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(command.entityId(), command.getLoanId()));
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
if (loan.getStatus().isClosed() && loan.getLoanSubStatus() != null
|
||||
&& loan.getLoanSubStatus().equals(LoanSubStatus.FORECLOSED.getValue())) {
|
||||
if (loan.getStatus().isClosed() && loan.getLoanSubStatus() != null && loan.getLoanSubStatus().equals(LoanSubStatus.FORECLOSED)) {
|
||||
final String defaultUserMessage = "The loan cannot reopened as it is foreclosed.";
|
||||
throw new LoanForeclosureException("loan.cannot.be.reopened.as.it.is.foreclosured", defaultUserMessage, loanId);
|
||||
}
|
||||
@@ -2067,9 +2066,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final WorkingDays workingDays = this.workingDaysRepository.findOne();
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
|
||||
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
|
||||
final Collection<Integer> loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP.getValue(), AccountType.JLG.getValue()));
|
||||
final Collection<LoanStatus> loanStatuses = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
|
||||
final Collection<AccountType> loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP, AccountType.JLG));
|
||||
final Collection<Long> loanIds = new ArrayList<>(loanCalendarInstances.size());
|
||||
// loop through loanCalendarInstances to get loan ids
|
||||
for (final CalendarInstance calendarInstance : loanCalendarInstances) {
|
||||
@@ -2134,10 +2133,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
if (loan.isGroupLoan()) {
|
||||
if (loan.loanProduct().isIncludeInBorrowerCycle()) {
|
||||
loansToUpdate = this.loanRepositoryWrapper.getGroupLoansToUpdateLoanCounter(loan.getCurrentLoanCounter(), loan.getGroupId(),
|
||||
AccountType.GROUP.getValue());
|
||||
AccountType.GROUP);
|
||||
} else {
|
||||
loansToUpdate = this.loanRepositoryWrapper.getGroupLoansToUpdateLoanProductCounter(loan.getLoanProductLoanCounter(),
|
||||
loan.getGroupId(), AccountType.GROUP.getValue());
|
||||
loan.getGroupId(), AccountType.GROUP);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -2162,7 +2161,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
if (loan.isGroupLoan()) {
|
||||
final List<Loan> loansToUpdateForLoanCounter = this.loanRepositoryWrapper.getGroupLoansDisbursedAfter(actualDisbursementDate,
|
||||
loan.getGroupId(), AccountType.GROUP.getValue());
|
||||
loan.getGroupId(), AccountType.GROUP);
|
||||
final Integer newLoanCounter = getNewGroupLoanCounter(loan);
|
||||
final Integer newLoanProductCounter = getNewGroupLoanProductCounter(loan);
|
||||
updateLoanCounter(loan, loansToUpdateForLoanCounter, newLoanCounter, newLoanProductCounter);
|
||||
@@ -2177,7 +2176,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
private Integer getNewGroupLoanCounter(final Loan loan) {
|
||||
|
||||
Integer maxClientLoanCounter = this.loanRepositoryWrapper.getMaxGroupLoanCounter(loan.getGroupId(), AccountType.GROUP.getValue());
|
||||
Integer maxClientLoanCounter = this.loanRepositoryWrapper.getMaxGroupLoanCounter(loan.getGroupId(), AccountType.GROUP);
|
||||
if (maxClientLoanCounter == null) {
|
||||
maxClientLoanCounter = 1;
|
||||
} else {
|
||||
@@ -2189,7 +2188,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private Integer getNewGroupLoanProductCounter(final Loan loan) {
|
||||
|
||||
Integer maxLoanProductLoanCounter = this.loanRepositoryWrapper.getMaxGroupLoanProductCounter(loan.loanProduct().getId(),
|
||||
loan.getGroupId(), AccountType.GROUP.getValue());
|
||||
loan.getGroupId(), AccountType.GROUP);
|
||||
if (maxLoanProductLoanCounter == null) {
|
||||
maxLoanProductLoanCounter = 1;
|
||||
} else {
|
||||
|
||||
+5
-7
@@ -63,18 +63,16 @@ public class ProgressiveLoanInterestRefundServiceImpl implements InterestRefundS
|
||||
|
||||
private static void simulateRepaymentForDisbursements(LoanTransaction lt, final AtomicReference<BigDecimal> refundFinal,
|
||||
List<LoanTransaction> collect) {
|
||||
collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), lt.getTypeOf().getValue(), lt.getDateOf(), lt.getAmount(),
|
||||
collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), lt.getTypeOf(), lt.getDateOf(), lt.getAmount(),
|
||||
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null));
|
||||
if (lt.getTypeOf().isDisbursement() && MathUtil.isGreaterThanZero(refundFinal.get())) {
|
||||
if (lt.getAmount().compareTo(refundFinal.get()) <= 0) {
|
||||
collect.add(
|
||||
new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT.getValue(), lt.getDateOf(), lt.getAmount(),
|
||||
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null));
|
||||
collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT, lt.getDateOf(), lt.getAmount(),
|
||||
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null));
|
||||
refundFinal.set(refundFinal.get().subtract(lt.getAmount()));
|
||||
} else {
|
||||
collect.add(
|
||||
new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT.getValue(), lt.getDateOf(), refundFinal.get(),
|
||||
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null));
|
||||
collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT, lt.getDateOf(), refundFinal.get(),
|
||||
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null));
|
||||
refundFinal.set(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -176,8 +176,8 @@ public class LoanReAgingServiceImpl {
|
||||
Money txPrincipal = loan.getTotalPrincipalOutstandingUntil(transactionDate);
|
||||
BigDecimal txPrincipalAmount = txPrincipal.getAmount();
|
||||
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAGE.getValue(), transactionDate, txPrincipalAmount,
|
||||
txPrincipalAmount, ZERO, ZERO, ZERO, null, false, null, txExternalId);
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAGE, transactionDate, txPrincipalAmount, txPrincipalAmount,
|
||||
ZERO, ZERO, ZERO, null, false, null, txExternalId);
|
||||
}
|
||||
|
||||
private LoanReAgeParameter createReAgeParameter(LoanTransaction reAgeTransaction, JsonCommand command) {
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ public class LoanReAmortizationServiceImpl {
|
||||
Money txPrincipal = loan.getTotalPrincipalOutstandingUntil(transactionDate);
|
||||
BigDecimal txPrincipalAmount = txPrincipal.getAmount();
|
||||
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAMORTIZE.getValue(), transactionDate, txPrincipalAmount,
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAMORTIZE, transactionDate, txPrincipalAmount,
|
||||
txPrincipalAmount, ZERO, ZERO, ZERO, null, false, null, txExternalId);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1704,8 +1704,8 @@ public final class LoanProductDataValidator {
|
||||
}
|
||||
if (actualValue) {
|
||||
Integer ruleType = accountingRuleType;
|
||||
if (ruleType == null) {
|
||||
ruleType = loanProduct.getAccountingRule();
|
||||
if (ruleType == null && loanProduct.getAccountingRule() != null) {
|
||||
ruleType = loanProduct.getAccountingRule().getValue();
|
||||
}
|
||||
if (!AccountingValidations.isAccrualBasedAccounting(ruleType)) {
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.ENABLE_ACCRUAL_ACTIVITY_POSTING)
|
||||
|
||||
+6
-1
@@ -22,6 +22,8 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
@@ -52,6 +54,7 @@ import org.apache.fineract.portfolio.group.exception.ClientNotInGroupException;
|
||||
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanOfficerService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
@@ -151,8 +154,10 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
final CalendarInstance sourceGroupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||
sourceGroup.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue());
|
||||
// get all customer loans synced with this group calendar Instance
|
||||
final Collection<LoanStatus> activeLoanStatuses = new ArrayList<>(
|
||||
Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
|
||||
final List<CalendarInstance> activeLoanCalendarInstances = this.calendarInstanceRepository
|
||||
.findCalendarInstancesForActiveLoansByGroupIdAndClientId(sourceGroup.getId(), client.getId());
|
||||
.findCalendarInstancesForLoansByGroupIdAndClientIdAndStatuses(sourceGroup.getId(), client.getId(), activeLoanStatuses);
|
||||
|
||||
/**
|
||||
* if a calendar is present in the source group along with loans synced with it, we should ensure that the
|
||||
|
||||
+1
-1
@@ -337,7 +337,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
||||
delinquencyEffectivePauseHelper, configurationDomainService);
|
||||
|
||||
Loan loan = Mockito.spy(Loan.class);
|
||||
ReflectionTestUtils.setField(loan, "loanStatus", 300);
|
||||
ReflectionTestUtils.setField(loan, "loanStatus", LoanStatus.ACTIVE);
|
||||
LoanTransaction transaction1 = Mockito.mock(LoanTransaction.class);
|
||||
LoanTransaction transaction2 = Mockito.mock(LoanTransaction.class);
|
||||
CollectionData collectionData = Mockito.mock(CollectionData.class);
|
||||
|
||||
+3
-3
@@ -154,7 +154,7 @@ public class LoanDelinquencyDomainServiceTest {
|
||||
when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0);
|
||||
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
|
||||
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
|
||||
when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK.getValue()))
|
||||
when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK))
|
||||
.thenReturn(Collections.emptyList());
|
||||
when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0));
|
||||
when(loan.getCurrency()).thenReturn(currency);
|
||||
@@ -223,7 +223,7 @@ public class LoanDelinquencyDomainServiceTest {
|
||||
when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0);
|
||||
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
|
||||
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
|
||||
when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK.getValue()))
|
||||
when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK))
|
||||
.thenReturn(Collections.emptyList());
|
||||
when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0));
|
||||
when(loan.getCurrency()).thenReturn(currency);
|
||||
@@ -279,7 +279,7 @@ public class LoanDelinquencyDomainServiceTest {
|
||||
when(loan.isEnableInstallmentLevelDelinquency()).thenReturn(true);
|
||||
when(loan.getCurrency()).thenReturn(currency);
|
||||
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
|
||||
when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK.getValue()))
|
||||
when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK))
|
||||
.thenReturn(Arrays.asList(loanTransaction));
|
||||
when(delinquencyEffectivePauseHelper.getPausedDaysBeforeDate(effectiveDelinquencyList, businessDate)).thenReturn(0L);
|
||||
|
||||
|
||||
+4
-9
@@ -142,7 +142,6 @@ class DefaultLoanLifecycleStateMachineTest {
|
||||
Loan loan = Mockito.mock(Loan.class);
|
||||
LoanSummary loanSummary = Mockito.mock(LoanSummary.class);
|
||||
Mockito.when(loan.getCurrency()).thenReturn(currency);
|
||||
Mockito.when(loan.getPlainStatus()).thenReturn(LoanStatus.OVERPAID.getValue());
|
||||
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.OVERPAID);
|
||||
Mockito.when(loan.getTotalOverpaidAsMoney()).thenReturn(zero);
|
||||
Mockito.when(loan.getSummary()).thenReturn(loanSummary);
|
||||
@@ -150,7 +149,7 @@ class DefaultLoanLifecycleStateMachineTest {
|
||||
// when
|
||||
underTest.transition(LoanEvent.LOAN_DISBURSED, loan);
|
||||
// then
|
||||
verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.ACTIVE.getValue());
|
||||
verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.ACTIVE);
|
||||
verify(businessEventNotifierService).notifyPostBusinessEvent(any(LoanStatusChangedBusinessEvent.class));
|
||||
}
|
||||
|
||||
@@ -162,7 +161,6 @@ class DefaultLoanLifecycleStateMachineTest {
|
||||
Loan loan = Mockito.mock(Loan.class);
|
||||
LoanSummary loanSummary = Mockito.mock(LoanSummary.class);
|
||||
Mockito.when(loan.getCurrency()).thenReturn(currency);
|
||||
Mockito.when(loan.getPlainStatus()).thenReturn(LoanStatus.OVERPAID.getValue());
|
||||
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.OVERPAID);
|
||||
Mockito.when(loan.getTotalOverpaidAsMoney()).thenReturn(zero);
|
||||
Mockito.when(loan.getSummary()).thenReturn(loanSummary);
|
||||
@@ -170,7 +168,7 @@ class DefaultLoanLifecycleStateMachineTest {
|
||||
// when
|
||||
underTest.transition(LoanEvent.LOAN_DISBURSED, loan);
|
||||
// then
|
||||
verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue());
|
||||
verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.CLOSED_OBLIGATIONS_MET);
|
||||
verify(businessEventNotifierService).notifyPostBusinessEvent(any(LoanStatusChangedBusinessEvent.class));
|
||||
}
|
||||
|
||||
@@ -179,13 +177,12 @@ class DefaultLoanLifecycleStateMachineTest {
|
||||
// given
|
||||
Money overpayment = Money.of(new MonetaryCurrency("USD", 2, null), BigDecimal.TEN);
|
||||
Loan loan = Mockito.mock(Loan.class);
|
||||
Mockito.when(loan.getPlainStatus()).thenReturn(LoanStatus.OVERPAID.getValue());
|
||||
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.OVERPAID);
|
||||
Mockito.when(loan.getTotalOverpaidAsMoney()).thenReturn(overpayment);
|
||||
// when
|
||||
underTest.transition(LoanEvent.LOAN_DISBURSED, loan);
|
||||
// then
|
||||
verify(loan, Mockito.never()).setLoanStatus(LoanStatus.ACTIVE.getValue());
|
||||
verify(loan, Mockito.never()).setLoanStatus(LoanStatus.ACTIVE);
|
||||
verify(businessEventNotifierService, Mockito.never()).notifyPostBusinessEvent(any(LoanStatusChangedBusinessEvent.class));
|
||||
}
|
||||
|
||||
@@ -422,9 +419,7 @@ class DefaultLoanLifecycleStateMachineTest {
|
||||
|
||||
private Loan createLoanWithStatus(LoanStatus status) {
|
||||
Loan result = new Loan();
|
||||
if (status != null) {
|
||||
result.setLoanStatus(status.getValue());
|
||||
}
|
||||
result.setLoanStatus(status);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -208,40 +208,40 @@ public class LoanTest {
|
||||
|
||||
LoanTransaction lt1 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt1, "id", 1L);
|
||||
ReflectionTestUtils.setField(lt1, "typeOf", LoanTransactionType.DISBURSEMENT.getValue());
|
||||
ReflectionTestUtils.setField(lt1, "typeOf", LoanTransactionType.DISBURSEMENT);
|
||||
ReflectionTestUtils.setField(lt1, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt1, "createdDate", now);
|
||||
LoanTransaction lt2 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt2, "id", 2L);
|
||||
ReflectionTestUtils.setField(lt2, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt2, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER);
|
||||
ReflectionTestUtils.setField(lt2, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt2, "createdDate", now);
|
||||
LoanTransaction lt3 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt3, "id", 3L);
|
||||
ReflectionTestUtils.setField(lt3, "typeOf", LoanTransactionType.REPAYMENT.getValue());
|
||||
ReflectionTestUtils.setField(lt3, "typeOf", LoanTransactionType.REPAYMENT);
|
||||
ReflectionTestUtils.setField(lt3, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt3, "createdDate", now);
|
||||
ReflectionTestUtils.setField(lt3, "reversed", true);
|
||||
LoanTransaction lt4 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt4, "id", 4L);
|
||||
ReflectionTestUtils.setField(lt4, "typeOf", LoanTransactionType.WAIVE_INTEREST.getValue());
|
||||
ReflectionTestUtils.setField(lt4, "typeOf", LoanTransactionType.WAIVE_INTEREST);
|
||||
ReflectionTestUtils.setField(lt4, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt4, "createdDate", now);
|
||||
LoanTransaction lt5 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt5, "id", 5L);
|
||||
ReflectionTestUtils.setField(lt5, "typeOf", LoanTransactionType.INCOME_POSTING.getValue());
|
||||
ReflectionTestUtils.setField(lt5, "typeOf", LoanTransactionType.INCOME_POSTING);
|
||||
ReflectionTestUtils.setField(lt5, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt5, "createdDate", now);
|
||||
LoanTransaction lt6 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt6, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt6, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER);
|
||||
ReflectionTestUtils.setField(lt6, "dateOf", today.minusDays(2));
|
||||
LoanTransaction lt7 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt7, "id", 7L);
|
||||
ReflectionTestUtils.setField(lt7, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt7, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER);
|
||||
ReflectionTestUtils.setField(lt7, "dateOf", today.minusDays(2));
|
||||
LoanTransaction lt8 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt8, "id", 8L);
|
||||
ReflectionTestUtils.setField(lt8, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt8, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER);
|
||||
ReflectionTestUtils.setField(lt8, "dateOf", today.minusDays(2));
|
||||
ReflectionTestUtils.setField(lt8, "createdDate", now.minusMinutes(2));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user