FINERACT-2080: use enums instead of integers in Loan, LoanProduct and LoanTransaction
This commit is contained in:
+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() {
|
||||
|
||||
Reference in New Issue
Block a user