FINERACT-1678: Performance improvement of Apply Charge to Overdue Loans COB Business Step
This commit is contained in:
committed by
Arnold Gálovics
parent
5bf9e1a288
commit
950f6489fe
+8
-9
@@ -59,7 +59,6 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGL
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepository;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
@@ -105,7 +104,7 @@ public class AccountingProcessorHelper {
|
||||
final Long loanId = (Long) accountingBridgeData.get("loanId");
|
||||
final Long loanProductId = (Long) accountingBridgeData.get("loanProductId");
|
||||
final Long officeId = (Long) accountingBridgeData.get("officeId");
|
||||
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
|
||||
final String currencyCode = (String) accountingBridgeData.get("currencyCode");
|
||||
final List<LoanTransactionDTO> newLoanTransactions = new ArrayList<>();
|
||||
boolean isAccountTransfer = (Boolean) accountingBridgeData.get("isAccountTransfer");
|
||||
|
||||
@@ -160,8 +159,8 @@ public class AccountingProcessorHelper {
|
||||
|
||||
}
|
||||
|
||||
return new LoanDTO(loanId, loanProductId, officeId, currencyData.code(), cashBasedAccountingEnabled,
|
||||
upfrontAccrualBasedAccountingEnabled, periodicAccrualBasedAccountingEnabled, newLoanTransactions);
|
||||
return new LoanDTO(loanId, loanProductId, officeId, currencyCode, cashBasedAccountingEnabled, upfrontAccrualBasedAccountingEnabled,
|
||||
periodicAccrualBasedAccountingEnabled, newLoanTransactions);
|
||||
}
|
||||
|
||||
public SavingsDTO populateSavingsDtoFromMap(final Map<String, Object> accountingBridgeData, final boolean cashBasedAccountingEnabled,
|
||||
@@ -169,7 +168,7 @@ public class AccountingProcessorHelper {
|
||||
final Long loanId = (Long) accountingBridgeData.get("savingsId");
|
||||
final Long loanProductId = (Long) accountingBridgeData.get("savingsProductId");
|
||||
final Long officeId = (Long) accountingBridgeData.get("officeId");
|
||||
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
|
||||
final String currencyCode = (String) accountingBridgeData.get("currencyCode");
|
||||
final List<SavingsTransactionDTO> newSavingsTransactions = new ArrayList<>();
|
||||
boolean isAccountTransfer = (Boolean) accountingBridgeData.get("isAccountTransfer");
|
||||
|
||||
@@ -230,8 +229,8 @@ public class AccountingProcessorHelper {
|
||||
|
||||
}
|
||||
|
||||
return new SavingsDTO(loanId, loanProductId, officeId, currencyData.code(), cashBasedAccountingEnabled,
|
||||
accrualBasedAccountingEnabled, newSavingsTransactions);
|
||||
return new SavingsDTO(loanId, loanProductId, officeId, currencyCode, cashBasedAccountingEnabled, accrualBasedAccountingEnabled,
|
||||
newSavingsTransactions);
|
||||
}
|
||||
|
||||
public SharesDTO populateSharesDtoFromMap(final Map<String, Object> accountingBridgeData, final boolean cashBasedAccountingEnabled,
|
||||
@@ -239,7 +238,7 @@ public class AccountingProcessorHelper {
|
||||
final Long shareAccountId = (Long) accountingBridgeData.get("shareAccountId");
|
||||
final Long shareProductId = (Long) accountingBridgeData.get("shareProductId");
|
||||
final Long officeId = (Long) accountingBridgeData.get("officeId");
|
||||
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
|
||||
final String currencyCode = (String) accountingBridgeData.get("currencyCode");
|
||||
final List<SharesTransactionDTO> newTransactions = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -275,7 +274,7 @@ public class AccountingProcessorHelper {
|
||||
|
||||
}
|
||||
|
||||
return new SharesDTO(shareAccountId, shareProductId, officeId, currencyData.code(), cashBasedAccountingEnabled,
|
||||
return new SharesDTO(shareAccountId, shareProductId, officeId, currencyCode, cashBasedAccountingEnabled,
|
||||
accrualBasedAccountingEnabled, newTransactions);
|
||||
}
|
||||
|
||||
|
||||
+6
-18
@@ -19,11 +19,7 @@
|
||||
package org.apache.fineract.cob.loan;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
@@ -34,24 +30,16 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class ApplyChargeToOverdueLoansBusinessStep implements LoanCOBBusinessStep {
|
||||
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final LoanReadPlatformService loanReadPlatformService;
|
||||
private final LoanWritePlatformService loanWritePlatformService;
|
||||
|
||||
@Override
|
||||
public Loan execute(Loan input) {
|
||||
final Long penaltyWaitPeriodValue = configurationDomainService.retrievePenaltyWaitPeriod();
|
||||
final Boolean backdatePenalties = configurationDomainService.isBackdatePenaltiesEnabled();
|
||||
final Collection<OverdueLoanScheduleData> overdueLoanScheduledInstallments = loanReadPlatformService
|
||||
.retrieveAllLoansWithOverdueInstallments(penaltyWaitPeriodValue, backdatePenalties);
|
||||
// TODO: this is very much not effective to get all overdue installments for each loan, a new method needs to be
|
||||
// implemented for it
|
||||
Map<Long, List<OverdueLoanScheduleData>> groupedOverdueData = overdueLoanScheduledInstallments.stream()
|
||||
.collect(Collectors.groupingBy(OverdueLoanScheduleData::getLoanId));
|
||||
for (Long loanId : groupedOverdueData.keySet()) {
|
||||
loanWritePlatformService.applyOverdueChargesForLoan(input.getId(), groupedOverdueData.get(loanId));
|
||||
}
|
||||
return input;
|
||||
public Loan execute(Loan loan) {
|
||||
final Collection<OverdueLoanScheduleData> overdueLoanScheduleDataList = loanReadPlatformService
|
||||
.retrieveAllOverdueInstallmentsForLoan(loan);
|
||||
|
||||
loanWritePlatformService.applyOverdueChargesForLoan(loan.getId(), overdueLoanScheduleDataList);
|
||||
return loan;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
-9
@@ -71,7 +71,6 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.holiday.service.HolidayUtil;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
@@ -2394,8 +2393,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public Collection<Long> findExistingTransactionIds() {
|
||||
final Collection<Long> ids = new ArrayList<>();
|
||||
public List<Long> findExistingTransactionIds() {
|
||||
final List<Long> ids = new ArrayList<>();
|
||||
List<LoanTransaction> transactions = getLoanTransactions();
|
||||
for (final LoanTransaction transaction : transactions) {
|
||||
ids.add(transaction.getId());
|
||||
@@ -2404,9 +2403,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return ids;
|
||||
}
|
||||
|
||||
public Collection<Long> findExistingReversedTransactionIds() {
|
||||
public List<Long> findExistingReversedTransactionIds() {
|
||||
|
||||
final Collection<Long> ids = new ArrayList<>();
|
||||
final List<Long> ids = new ArrayList<>();
|
||||
List<LoanTransaction> transactions = getLoanTransactions();
|
||||
for (final LoanTransaction transaction : transactions) {
|
||||
if (transaction.isReversed()) {
|
||||
@@ -4411,14 +4410,14 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return this.proposedPrincipal;
|
||||
}
|
||||
|
||||
public Map<String, Object> deriveAccountingBridgeData(final CurrencyData currencyData, final List<Long> existingTransactionIds,
|
||||
public Map<String, Object> deriveAccountingBridgeData(final String currencyCode, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
|
||||
|
||||
final Map<String, Object> accountingBridgeData = new LinkedHashMap<>();
|
||||
accountingBridgeData.put("loanId", getId());
|
||||
accountingBridgeData.put("loanProductId", productId());
|
||||
accountingBridgeData.put("officeId", getOfficeId());
|
||||
accountingBridgeData.put("currency", currencyData);
|
||||
accountingBridgeData.put("currencyCode", currencyCode);
|
||||
accountingBridgeData.put("calculatedInterest", this.summary.getTotalInterestCharged());
|
||||
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnLoanProduct());
|
||||
accountingBridgeData.put("upfrontAccrualBasedAccountingEnabled", isUpfrontAccrualAccountingEnabledOnLoanProduct());
|
||||
@@ -4429,9 +4428,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
for (final LoanTransaction transaction : this.loanTransactions) {
|
||||
if (transaction.isReversed() && existingTransactionIds.contains(transaction.getId())
|
||||
&& !existingReversedTransactionIds.contains(transaction.getId())) {
|
||||
newLoanTransactions.add(transaction.toMapData(currencyData));
|
||||
newLoanTransactions.add(transaction.toMapData(currencyCode));
|
||||
} else if (!existingTransactionIds.contains(transaction.getId())) {
|
||||
newLoanTransactions.add(transaction.toMapData(currencyData));
|
||||
newLoanTransactions.add(transaction.toMapData(currencyCode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-12
@@ -111,7 +111,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
private final HolidayRepository holidayRepository;
|
||||
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
||||
|
||||
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final NoteRepository noteRepository;
|
||||
private final AccountTransferRepository accountTransferRepository;
|
||||
@@ -417,10 +416,9 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer, boolean isLoanToLoanTransfer) {
|
||||
|
||||
final MonetaryCurrency currency = loanAccount.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
|
||||
|
||||
final Map<String, Object> accountingBridgeData = loanAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
final Map<String, Object> accountingBridgeData = loanAccount.deriveAccountingBridgeData(currency.getCode(), existingTransactionIds,
|
||||
existingReversedTransactionIds, isAccountTransfer);
|
||||
accountingBridgeData.put("isLoanToLoanTransfer", isLoanToLoanTransfer);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
@@ -535,14 +533,13 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
*/
|
||||
@Override
|
||||
public void recalculateAccruals(Loan loan) {
|
||||
boolean isInterestCalcualtionHappened = loan.repaymentScheduleDetail().isInterestRecalculationEnabled();
|
||||
recalculateAccruals(loan, isInterestCalcualtionHappened);
|
||||
recalculateAccruals(loan, loan.repaymentScheduleDetail().isInterestRecalculationEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculateAccruals(Loan loan, boolean isInterestCalcualtionHappened) {
|
||||
public void recalculateAccruals(Loan loan, boolean isInterestCalculationHappened) {
|
||||
LocalDate accruedTill = loan.getAccruedTill();
|
||||
if (!loan.isPeriodicAccrualAccountingEnabledOnLoanProduct() || !isInterestCalcualtionHappened || accruedTill == null || loan.isNpa()
|
||||
if (!loan.isPeriodicAccrualAccountingEnabledOnLoanProduct() || !isInterestCalculationHappened || accruedTill == null || loan.isNpa()
|
||||
|| !loan.status().isActive()) {
|
||||
return;
|
||||
}
|
||||
@@ -552,7 +549,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
if (isOrganisationDateEnabled) {
|
||||
organisationStartDate = this.configurationDomainService.retrieveOrganisationStartDate();
|
||||
}
|
||||
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = new ArrayList<>();
|
||||
Collection<LoanScheduleAccrualData> loanScheduleAccrualList = new ArrayList<>();
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
Long loanId = loan.getId();
|
||||
Long officeId = loan.getOfficeId();
|
||||
@@ -571,15 +568,15 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
accruedTill = DateUtils.getBusinessLocalDate();
|
||||
}
|
||||
if (!isOrganisationDateEnabled || organisationStartDate.isBefore(installment.getDueDate())) {
|
||||
generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualDatas, loanId, officeId, accrualStartDate,
|
||||
generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualList, loanId, officeId, accrualStartDate,
|
||||
repaymentFrequency, repayEvery, interestCalculatedFrom, loanProductId, currency, currencyData, loanCharges,
|
||||
installment);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loanScheduleAccrualDatas.isEmpty()) {
|
||||
if (!loanScheduleAccrualList.isEmpty()) {
|
||||
try {
|
||||
this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill, loanScheduleAccrualDatas);
|
||||
this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill, loanScheduleAccrualList);
|
||||
} catch (MultiException e) {
|
||||
String globalisationMessageCode = "error.msg.accrual.exception";
|
||||
throw new GeneralPlatformDomainRuleException(globalisationMessageCode, e.getMessage(), e);
|
||||
|
||||
+2
-5
@@ -23,9 +23,11 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Table(name = "m_loan_overdue_installment_charge")
|
||||
public class LoanOverdueInstallmentCharge extends AbstractPersistableCustom {
|
||||
|
||||
@@ -54,9 +56,4 @@ public class LoanOverdueInstallmentCharge extends AbstractPersistableCustom {
|
||||
public void updateLoanRepaymentScheduleInstallment(LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
||||
this.installment = loanRepaymentScheduleInstallment;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment getInstallment() {
|
||||
return this.installment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -656,7 +656,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
transfer, null, outstandingLoanBalance, this.unrecognizedIncomePortion, this.manuallyAdjustedOrReversed);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMapData(final CurrencyData currencyData) {
|
||||
public Map<String, Object> toMapData(final String currencyCode) {
|
||||
final Map<String, Object> thisTransactionData = new LinkedHashMap<>();
|
||||
|
||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(this.typeOf);
|
||||
@@ -666,7 +666,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
thisTransactionData.put("type", transactionType);
|
||||
thisTransactionData.put("reversed", Boolean.valueOf(isReversed()));
|
||||
thisTransactionData.put("date", getTransactionDate());
|
||||
thisTransactionData.put("currency", currencyData);
|
||||
thisTransactionData.put("currencyCode", currencyCode);
|
||||
thisTransactionData.put("amount", this.amount);
|
||||
thisTransactionData.put("netDisbursalAmount", this.loan.getNetDisbursalAmount());
|
||||
thisTransactionData.put("principalPortion", this.principalPortion);
|
||||
|
||||
+2
-8
@@ -42,8 +42,6 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
@@ -99,7 +97,6 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
private final PlatformSecurityContext platformSecurityContext;
|
||||
private final LoanRescheduleRequestDataValidator loanRescheduleRequestDataValidator;
|
||||
private final LoanRescheduleRequestRepository loanRescheduleRequestRepository;
|
||||
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository;
|
||||
private final LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository;
|
||||
private final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
@@ -125,7 +122,6 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
final PlatformSecurityContext platformSecurityContext,
|
||||
final LoanRescheduleRequestDataValidator loanRescheduleRequestDataValidator,
|
||||
final LoanRescheduleRequestRepository loanRescheduleRequestRepository,
|
||||
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository,
|
||||
final LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository,
|
||||
final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService,
|
||||
final LoanTransactionRepository loanTransactionRepository,
|
||||
@@ -140,7 +136,6 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
this.platformSecurityContext = platformSecurityContext;
|
||||
this.loanRescheduleRequestDataValidator = loanRescheduleRequestDataValidator;
|
||||
this.loanRescheduleRequestRepository = loanRescheduleRequestRepository;
|
||||
this.applicationCurrencyRepository = applicationCurrencyRepository;
|
||||
this.loanRepaymentScheduleHistoryRepository = loanRepaymentScheduleHistoryRepository;
|
||||
this.loanScheduleHistoryWritePlatformService = loanScheduleHistoryWritePlatformService;
|
||||
this.loanTransactionRepository = loanTransactionRepository;
|
||||
@@ -538,10 +533,9 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
|
||||
private void postJournalEntries(Loan loan, List<Long> existingTransactionIds, List<Long> existingReversedTransactionIds) {
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.getCode(), existingTransactionIds,
|
||||
existingReversedTransactionIds, isAccountTransfer);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
|
||||
+3
-9
@@ -33,8 +33,6 @@ import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlat
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||
@@ -49,7 +47,6 @@ import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -64,10 +61,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final AppUserRepositoryWrapper userRepository;
|
||||
private final PlatformSecurityContext context;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@@ -289,7 +284,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
accountingBridgeData.put("loanId", loanScheduleAccrualData.getLoanId());
|
||||
accountingBridgeData.put("loanProductId", loanScheduleAccrualData.getLoanProductId());
|
||||
accountingBridgeData.put("officeId", loanScheduleAccrualData.getOfficeId());
|
||||
accountingBridgeData.put("currency", loanScheduleAccrualData.getCurrencyData());
|
||||
accountingBridgeData.put("currencyCode", loanScheduleAccrualData.getCurrencyData().getCode());
|
||||
accountingBridgeData.put("cashBasedAccountingEnabled", false);
|
||||
accountingBridgeData.put("upfrontAccrualBasedAccountingEnabled", false);
|
||||
accountingBridgeData.put("periodicAccrualBasedAccountingEnabled", true);
|
||||
@@ -489,10 +484,9 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
private void postJournalEntries(final Loan loan, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.getCode(), existingTransactionIds,
|
||||
existingReversedTransactionIds, isAccountTransfer);
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -20,9 +20,11 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
|
||||
public interface LoanChargeReadPlatformService {
|
||||
@@ -37,7 +39,7 @@ public interface LoanChargeReadPlatformService {
|
||||
|
||||
Collection<LoanInstallmentChargeData> retrieveInstallmentLoanCharges(Long loanChargeId, boolean onlyPaymentPendingCharges);
|
||||
|
||||
Collection<Integer> retrieveOverdueInstallmentChargeFrequencyNumber(Long loanId, Long chargeId, Integer periodNumber);
|
||||
Collection<Integer> retrieveOverdueInstallmentChargeFrequencyNumber(Loan loan, Charge charge, Integer periodNumber);
|
||||
|
||||
Collection<LoanChargeData> retrieveLoanChargesForAccural(Long loanId);
|
||||
|
||||
|
||||
+13
-10
@@ -31,15 +31,17 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeDropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
|
||||
import org.apache.fineract.portfolio.common.service.DropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -51,7 +53,6 @@ import org.springframework.stereotype.Service;
|
||||
public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService;
|
||||
private final DropdownReadPlatformService dropdownReadPlatformService;
|
||||
|
||||
@@ -243,16 +244,18 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Integer> retrieveOverdueInstallmentChargeFrequencyNumber(final Long loanId, final Long chargeId,
|
||||
public Collection<Integer> retrieveOverdueInstallmentChargeFrequencyNumber(final Loan loan, final Charge charge,
|
||||
final Integer periodNumber) {
|
||||
String sql = "select oic.frequency_number from m_loan_overdue_installment_charge oic inner join m_loan_charge lc on lc.id=oic.loan_charge_id inner join m_loan_repayment_schedule rs on rs.id = oic.loan_schedule_id inner join m_loan loan on loan.id=rs.loan_id "
|
||||
+ "where lc.is_active = true and loan.id = ? and rs.installment=?";
|
||||
Object[] params = { loanId, periodNumber };
|
||||
if (chargeId != null) {
|
||||
sql += " and lc.charge_id = ? ";
|
||||
params = new Object[] { loanId, periodNumber, chargeId };
|
||||
|
||||
List<Integer> frequencyNumbers = new ArrayList<>();
|
||||
for (LoanCharge loanCharge : loan.getLoanCharges()) {
|
||||
if (loanCharge.isOverdueInstallmentCharge() && charge.equals(loanCharge.getCharge()) && loanCharge.isActive()
|
||||
&& periodNumber.equals(loanCharge.getOverdueInstallmentCharge().getInstallment().getInstallmentNumber())) {
|
||||
frequencyNumbers.add(loanCharge.getOverdueInstallmentCharge().getFrequencyNumber());
|
||||
}
|
||||
}
|
||||
return this.jdbcTemplate.queryForList(sql, Integer.class, params);
|
||||
|
||||
return frequencyNumbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -38,6 +38,7 @@ import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
||||
@@ -93,6 +94,8 @@ public interface LoanReadPlatformService {
|
||||
*/
|
||||
Collection<OverdueLoanScheduleData> retrieveAllLoansWithOverdueInstallments(Long penaltyWaitPeriod, Boolean backdatePenalties);
|
||||
|
||||
Collection<OverdueLoanScheduleData> retrieveAllOverdueInstallmentsForLoan(Loan loan);
|
||||
|
||||
Integer retriveLoanCounter(Long groupId, Integer loanType, Long productId);
|
||||
|
||||
Integer retriveLoanCounter(Long clientId, Long productId);
|
||||
|
||||
+48
-5
@@ -31,7 +31,9 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
@@ -63,6 +65,7 @@ import org.apache.fineract.portfolio.calendar.data.CalendarData;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarReadPlatformService;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||
@@ -151,7 +154,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
private final CalendarReadPlatformService calendarReadPlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
private final PaginationHelper paginationHelper;
|
||||
private final LoanMapper loaanLoanMapper;
|
||||
private final LoanMapper loanMapper;
|
||||
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
private final PaymentTypeReadPlatformService paymentTypeReadPlatformService;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
@@ -199,7 +202,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.accountDetailsReadPlatformService = accountDetailsReadPlatformService;
|
||||
this.columnValidator = columnValidator;
|
||||
this.loaanLoanMapper = new LoanMapper(sqlGenerator, delinquencyReadPlatformService);
|
||||
this.loanMapper = new LoanMapper(sqlGenerator, delinquencyReadPlatformService);
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
this.paginationHelper = paginationHelper;
|
||||
this.delinquencyReadPlatformService = delinquencyReadPlatformService;
|
||||
@@ -303,7 +306,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
|
||||
sqlBuilder.append(this.loaanLoanMapper.loanSchema());
|
||||
sqlBuilder.append(this.loanMapper.loanSchema());
|
||||
|
||||
// TODO - for time being this will data scope list of loans returned to
|
||||
// only loans that have a client associated.
|
||||
@@ -367,7 +370,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
}
|
||||
final Object[] objectArray = extraCriterias.toArray();
|
||||
final Object[] finalObjectArray = Arrays.copyOf(objectArray, arrayPos);
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlBuilder.toString(), finalObjectArray, this.loaanLoanMapper);
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlBuilder.toString(), finalObjectArray, this.loanMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1040,7 +1043,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final BigDecimal amount = rs.getBigDecimal("amount");
|
||||
final String dateFormat = "yyyy-MM-dd";
|
||||
final String dueDate = rs.getString("dueDate");
|
||||
final String locale = "en_GB";
|
||||
final String locale = Locale.ENGLISH.toLanguageTag();
|
||||
|
||||
final BigDecimal principalDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalDue");
|
||||
final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalPaid");
|
||||
@@ -1558,6 +1561,46 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
return this.jdbcTemplate.query(sqlBuilder.toString(), rm, penaltyWaitPeriod, penaltyWaitPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<OverdueLoanScheduleData> retrieveAllOverdueInstallmentsForLoan(final Loan loan) {
|
||||
Collection<OverdueLoanScheduleData> list = new ArrayList<>();
|
||||
|
||||
if (!loan.isOpen()) {
|
||||
return list;
|
||||
}
|
||||
final Long penaltyWaitPeriod = configurationDomainService.retrievePenaltyWaitPeriod();
|
||||
final boolean backdatePenalties = configurationDomainService.isBackdatePenaltiesEnabled();
|
||||
|
||||
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
|
||||
if (installment.isObligationsMet() || installment.isRecalculatedInterestComponent()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean isPenaltyDue = installment.isOverdueOn(DateUtils.getBusinessLocalDate().plusDays(penaltyWaitPeriod + 1));
|
||||
boolean isDueToday = installment.getDueDate().equals(DateUtils.getBusinessLocalDate().plusDays(penaltyWaitPeriod));
|
||||
|
||||
if (isPenaltyDue) {
|
||||
if (!backdatePenalties && !isDueToday) {
|
||||
continue;
|
||||
}
|
||||
Optional<Charge> penaltyCharge = loan.getLoanProduct().getLoanProductCharges().stream()
|
||||
.filter((e) -> ChargeTimeType.OVERDUE_INSTALLMENT.getValue().equals(e.getChargeTimeType()) && e.isLoanCharge())
|
||||
.findFirst();
|
||||
|
||||
if (penaltyCharge.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list.add(new OverdueLoanScheduleData(loan.getId(), penaltyCharge.get().getId(),
|
||||
DateUtils.DEFAULT_DATE_FORMATTER.format(installment.getDueDate()), penaltyCharge.get().getAmount(),
|
||||
DateUtils.DEFAULT_DATE_FORMAT, Locale.ENGLISH.toLanguageTag(),
|
||||
installment.getPrincipalOutstanding(loan.getCurrency()).getAmount(),
|
||||
installment.getInterestOutstanding(loan.getCurrency()).getAmount(), installment.getInstallmentNumber()));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Integer retriveLoanCounter(final Long groupId, final Integer loanType, Long productId) {
|
||||
|
||||
+70
-97
@@ -33,6 +33,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -57,8 +58,6 @@ import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChe
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
@@ -120,6 +119,7 @@ import org.apache.fineract.portfolio.calendar.domain.CalendarType;
|
||||
import org.apache.fineract.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeCannotBeAppliedToException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeCannotBeUpdatedException;
|
||||
import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeAddedException;
|
||||
import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeDeletedException;
|
||||
@@ -235,7 +235,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private final LoanAssembler loanAssembler;
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
private final LoanChargeRepository loanChargeRepository;
|
||||
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||
@@ -828,7 +827,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
//
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
|
||||
final LocalDate recalculateFrom = null;
|
||||
loan.setActualDisbursementDate(null);
|
||||
@@ -852,7 +850,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
this.accountTransfersWritePlatformService.reverseAllTransactions(loanId, PortfolioAccountType.LOAN);
|
||||
String noteText = null;
|
||||
String noteText;
|
||||
if (command.hasParameter("note")) {
|
||||
noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
@@ -861,8 +859,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.getCode(), existingTransactionIds,
|
||||
existingReversedTransactionIds, isAccountTransfer);
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoDisbursalBusinessEvent(loan));
|
||||
}
|
||||
@@ -887,9 +885,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
glimRepository.findById(parentLoanId).orElseThrow();
|
||||
|
||||
JsonArray repayments = command.arrayOfParameterNamed("formDataArray");
|
||||
JsonCommand childCommand = null;
|
||||
JsonCommand childCommand;
|
||||
CommandProcessingResult result = null;
|
||||
JsonObject jsonObject = null;
|
||||
JsonObject jsonObject;
|
||||
|
||||
Long[] childLoanId = new Long[repayments.size()];
|
||||
for (int i = 0; i < repayments.size(); i++) {
|
||||
@@ -982,7 +980,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
List<Long> transactionIds = new ArrayList<>();
|
||||
boolean isAccountTransfer = false;
|
||||
HolidayDetailDTO holidayDetailDTO = null;
|
||||
Boolean isHolidayValidationDone = false;
|
||||
boolean isHolidayValidationDone = false;
|
||||
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
|
||||
for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) {
|
||||
if (singleLoanRepaymentCommand != null) {
|
||||
@@ -991,7 +989,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
singleLoanRepaymentCommand.getTransactionDate());
|
||||
final WorkingDays workingDays = this.workingDaysRepository.findOne();
|
||||
final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled();
|
||||
boolean isHolidayEnabled = false;
|
||||
boolean isHolidayEnabled;
|
||||
isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
|
||||
holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday,
|
||||
allowTransactionsOnNonWorkingDay);
|
||||
@@ -1033,7 +1031,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
if (loan.status().isClosed() && loan.getLoanSubStatus() != null
|
||||
&& loan.getLoanSubStatus().equals(LoanSubStatus.FORECLOSED.getValue())) {
|
||||
final String defaultUserMessage = "The loan cannot reopend as it is 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);
|
||||
}
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -1121,7 +1119,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
changes.put("note", noteText);
|
||||
Note note = null;
|
||||
Note note;
|
||||
/**
|
||||
* If a new transaction is not created, associate note with the transaction to be adjusted
|
||||
**/
|
||||
@@ -1165,8 +1163,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public CommandProcessingResult waiveInterestOnLoan(final Long loanId, final JsonCommand command) {
|
||||
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
this.loanEventApiJsonValidator.validateTransaction(command.json());
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
@@ -1304,8 +1300,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public CommandProcessingResult closeLoan(final Long loanId, final JsonCommand command) {
|
||||
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
this.loanEventApiJsonValidator.validateTransactionWithNoAmount(command.json());
|
||||
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
@@ -1373,7 +1367,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
// disable all active standing instructions linked to the loan
|
||||
this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan);
|
||||
|
||||
CommandProcessingResult result = null;
|
||||
CommandProcessingResult result;
|
||||
if (possibleClosingTransaction != null) {
|
||||
|
||||
result = new CommandProcessingResultBuilder().withCommandId(command.commandId())
|
||||
@@ -1485,7 +1479,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LoanCharge loanCharge = null;
|
||||
LocalDate recalculateFrom = loan.fetchInterestRecalculateFromDate();
|
||||
if (chargeDefinition.isPercentageOfDisbursementAmount()) {
|
||||
LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = null;
|
||||
LoanTrancheDisbursementCharge loanTrancheDisbursementCharge;
|
||||
for (LoanDisbursementDetails disbursementDetail : loanDisburseDetails) {
|
||||
if (disbursementDetail.actualDisbursementDate() == null) {
|
||||
loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), null, null, null,
|
||||
@@ -1501,6 +1495,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loanCharge == null) {
|
||||
final String errorMessage = "Charge with identifier " + chargeDefinition.getId()
|
||||
+ " cannot be applied: No valid loan disbursement available";
|
||||
throw new ChargeCannotBeAppliedToException("loan", errorMessage, chargeDefinition.getId());
|
||||
}
|
||||
loan.addTrancheLoanCharge(chargeDefinition);
|
||||
} else {
|
||||
loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command);
|
||||
@@ -1607,7 +1606,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
private boolean addCharge(final Loan loan, final Charge chargeDefinition, final LoanCharge loanCharge) {
|
||||
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())) {
|
||||
final String errorMessage = "Charge and Loan must have the same currency.";
|
||||
throw new InvalidCurrencyException("loanCharge", "attach.to.loan", errorMessage);
|
||||
@@ -1634,11 +1632,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null);
|
||||
this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
|
||||
}
|
||||
boolean isAppliedOnBackDate = false;
|
||||
if (loanCharge.getDueLocalDate() == null || DateUtils.getBusinessLocalDate().isAfter(loanCharge.getDueLocalDate())) {
|
||||
isAppliedOnBackDate = true;
|
||||
}
|
||||
return isAppliedOnBackDate;
|
||||
return loanCharge.getDueLocalDate() == null || DateUtils.getBusinessLocalDate().isAfter(loanCharge.getDueLocalDate());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -1694,7 +1688,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
final BigDecimal fullRefundAbleAmount = loanChargeValidateRefundAmount(loanCharge, installmentChargeEntry, transactionAmount);
|
||||
|
||||
JsonCommand repaymentJsonCommand = adaptLoanChargeRefundCommandForFutherRepaymentProcessing(command, fullRefundAbleAmount);
|
||||
JsonCommand repaymentJsonCommand = adaptLoanChargeRefundCommandForFurtherRepaymentProcessing(command, fullRefundAbleAmount);
|
||||
|
||||
boolean isRecoveryRepayment = false;
|
||||
String chargeRefundChargeType = "F";
|
||||
@@ -1709,7 +1703,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
Long loanChargeRefundTransactionId = result.resourceId();
|
||||
LoanTransaction newChargeRefundTxn = null;
|
||||
for (LoanTransaction chargeRefundTxn : loanCharge.getLoan().getLoanTransactions()) {
|
||||
if (chargeRefundTxn.getId().equals(loanChargeRefundTransactionId)) {
|
||||
if (loanChargeRefundTransactionId.equals(chargeRefundTxn.getId())) {
|
||||
newChargeRefundTxn = chargeRefundTxn;
|
||||
final BigDecimal appliedRefundAmount = newChargeRefundTxn.getAmount(loanCharge.getLoan().getCurrency()).getAmount()
|
||||
.multiply(BigDecimal.valueOf(-1));
|
||||
@@ -1726,7 +1720,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
}
|
||||
|
||||
private JsonCommand adaptLoanChargeRefundCommandForFutherRepaymentProcessing(JsonCommand command, BigDecimal fullRefundAbleAmount) {
|
||||
private JsonCommand adaptLoanChargeRefundCommandForFurtherRepaymentProcessing(JsonCommand command, BigDecimal fullRefundAbleAmount) {
|
||||
// creates JsonCommand for onward repayment processing
|
||||
JsonObject jsonObject = (JsonObject) this.fromApiJsonHelper.parse(command.json());
|
||||
|
||||
@@ -1748,14 +1742,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
jsonObject.remove("installmentNumber");
|
||||
jsonObject.remove("dueDate");
|
||||
|
||||
JsonCommand repaymentJsonCommand = JsonCommand.fromExistingCommand(command, jsonObject);
|
||||
return repaymentJsonCommand;
|
||||
return JsonCommand.fromExistingCommand(command, jsonObject);
|
||||
}
|
||||
|
||||
private BigDecimal loanChargeValidateRefundAmount(LoanCharge loanCharge, LoanInstallmentCharge installmentChargeEntry,
|
||||
BigDecimal transactionAmount) {
|
||||
// if transactionAmount not provided return max refundable amount (amount paid minus previous refunds)
|
||||
BigDecimal chargeAmountPaid = BigDecimal.ZERO;
|
||||
BigDecimal chargeAmountPaid;
|
||||
BigDecimal chargeAmountRefunded = BigDecimal.ZERO;
|
||||
MonetaryCurrency loanCurrency = loanCharge.getLoan().getCurrency();
|
||||
if (loanCharge.isInstalmentFee()) {
|
||||
@@ -1780,7 +1773,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
if (chargeAmountRefunded.compareTo(chargeAmountPaid) > 0) {
|
||||
final String errorMessage = "loan.charge.more.refunded.than.paid.unexpected.system.error";
|
||||
final String details = "Paid: " + chargeAmountPaid.toString() + " Refunded: " + chargeAmountPaid.toString();
|
||||
final String details = "Paid: " + chargeAmountPaid.toString() + " Refunded: " + chargeAmountPaid;
|
||||
throw new LoanChargeRefundException(errorMessage, details);
|
||||
}
|
||||
|
||||
@@ -1788,8 +1781,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
if (transactionAmount != null) { // refund amount was provided.
|
||||
if (transactionAmount.compareTo(refundableAmount) > 0) {
|
||||
final String errorMessage = "loan.charge.transaction.amount.is.more.than.is.refundable";
|
||||
final String details = "transactionAmount: " + transactionAmount.toString() + " Refundable: "
|
||||
+ refundableAmount.toString();
|
||||
final String details = "transactionAmount: " + transactionAmount + " Refundable: " + refundableAmount;
|
||||
throw new LoanChargeRefundException(errorMessage, details);
|
||||
}
|
||||
}
|
||||
@@ -1900,7 +1892,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanWaiveChargeUndoBusinessEvent(loanCharge));
|
||||
|
||||
if (loanCharge.isInstalmentFee()) {
|
||||
LoanInstallmentCharge chargePerInstallment = null;
|
||||
LoanInstallmentCharge chargePerInstallment;
|
||||
|
||||
// final Integer installmentNumber = command.integerValueOfParameterNamed("installmentNumber");
|
||||
if (installmentNumber != null) {
|
||||
@@ -2004,8 +1996,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public CommandProcessingResult waiveLoanCharge(final Long loanId, final Long loanChargeId, final JsonCommand command) {
|
||||
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
this.loanEventApiJsonValidator.validateInstallmentChargeTransaction(command.json());
|
||||
@@ -2056,9 +2046,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
Money accruedCharge = Money.zero(loan.getCurrency());
|
||||
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
Collection<LoanChargePaidByData> chargePaidByDatas = this.loanChargeReadPlatformService
|
||||
Collection<LoanChargePaidByData> chargePaidByCollection = this.loanChargeReadPlatformService
|
||||
.retriveLoanChargesPaidBy(loanCharge.getId(), LoanTransactionType.ACCRUAL, loanInstallmentNumber);
|
||||
for (LoanChargePaidByData chargePaidByData : chargePaidByDatas) {
|
||||
for (LoanChargePaidByData chargePaidByData : chargePaidByCollection) {
|
||||
accruedCharge = accruedCharge.plus(chargePaidByData.getAmount());
|
||||
}
|
||||
}
|
||||
@@ -2409,7 +2399,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
loanUpdateCommand.validate();
|
||||
|
||||
final LocalDate dateOfLoanOfficerunAssigned = command.localDateValueOfParameterNamed("unassignedDate");
|
||||
final LocalDate dateOfLoanOfficerUnassigned = command.localDateValueOfParameterNamed("unassignedDate");
|
||||
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -2419,7 +2409,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanRemoveOfficerBusinessEvent(loan));
|
||||
|
||||
loan.removeLoanOfficer(dateOfLoanOfficerunAssigned);
|
||||
loan.removeLoanOfficer(dateOfLoanOfficerUnassigned);
|
||||
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanRemoveOfficerBusinessEvent(loan));
|
||||
@@ -2438,10 +2428,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.getCode(), existingTransactionIds,
|
||||
existingReversedTransactionIds, isAccountTransfer);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
@@ -2449,22 +2438,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public void applyMeetingDateChanges(final Calendar calendar, final Collection<CalendarInstance> loanCalendarInstances) {
|
||||
|
||||
final Boolean reschedulebasedOnMeetingDates = null;
|
||||
final Boolean rescheduleBasedOnMeetingDates = null;
|
||||
final LocalDate presentMeetingDate = null;
|
||||
final LocalDate newMeetingDate = null;
|
||||
|
||||
applyMeetingDateChanges(calendar, loanCalendarInstances, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate);
|
||||
applyMeetingDateChanges(calendar, loanCalendarInstances, rescheduleBasedOnMeetingDates, presentMeetingDate, newMeetingDate);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void applyMeetingDateChanges(final Calendar calendar, final Collection<CalendarInstance> loanCalendarInstances,
|
||||
final Boolean reschedulebasedOnMeetingDates, final LocalDate presentMeetingDate, final LocalDate newMeetingDate) {
|
||||
final Boolean rescheduleBasedOnMeetingDates, final LocalDate presentMeetingDate, final LocalDate newMeetingDate) {
|
||||
|
||||
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
|
||||
final WorkingDays workingDays = this.workingDaysRepository.findOne();
|
||||
final AppUser currentUser = getAppUserIfPresent();
|
||||
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(),
|
||||
@@ -2477,7 +2465,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
final List<Loan> loans = this.loanRepositoryWrapper.findByIdsAndLoanStatusAndLoanType(loanIds, loanStatuses, loanTypes);
|
||||
List<Holiday> holidays = null;
|
||||
List<Holiday> holidays;
|
||||
final LocalDate recalculateFrom = null;
|
||||
// loop through each loan to reschedule the repayment dates
|
||||
for (final Loan loan : loans) {
|
||||
@@ -2489,7 +2477,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
Boolean isSkipRepaymentOnFirstMonth = false;
|
||||
Integer numberOfDays = 0;
|
||||
int numberOfDays = 0;
|
||||
boolean isSkipRepaymentOnFirstMonthEnabled = configurationDomainService.isSkippingMeetingOnFirstDayOfMonthEnabled();
|
||||
if (isSkipRepaymentOnFirstMonthEnabled) {
|
||||
isSkipRepaymentOnFirstMonth = this.loanUtilService.isLoanRepaymentsSyncWithMeeting(loan.group(), calendar);
|
||||
@@ -2505,9 +2493,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||
} else if (reschedulebasedOnMeetingDates != null && reschedulebasedOnMeetingDates) {
|
||||
} else if (rescheduleBasedOnMeetingDates != null && rescheduleBasedOnMeetingDates) {
|
||||
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
|
||||
holidays, workingDays, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate,
|
||||
holidays, workingDays, rescheduleBasedOnMeetingDates, presentMeetingDate, newMeetingDate,
|
||||
isSkipRepaymentOnFirstMonth, numberOfDays);
|
||||
} else {
|
||||
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
|
||||
@@ -2603,7 +2591,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanToUpdate.updateClientLoanCounter(++currentLoanCounter);
|
||||
}
|
||||
|
||||
if (loanToUpdate.loanProduct().getId().equals(loan.loanProduct().getId())) {
|
||||
if (Objects.equals(loan.loanProduct().getId(), loanToUpdate.loanProduct().getId())) {
|
||||
Integer loanProductLoanCounter = loanToUpdate.getLoanProductLoanCounter();
|
||||
if (newLoanProductCounter > loanProductLoanCounter) {
|
||||
newLoanProductCounter = loanProductLoanCounter;
|
||||
@@ -2646,17 +2634,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
private void updateLoanCycleCounter(final List<Loan> loansToUpdate, final Loan loan) {
|
||||
|
||||
final Integer currentLoancounter = loan.getCurrentLoanCounter();
|
||||
final Integer currentLoanCounter = loan.getCurrentLoanCounter();
|
||||
final Integer currentLoanProductCounter = loan.getLoanProductLoanCounter();
|
||||
|
||||
for (final Loan loanToUpdate : loansToUpdate) {
|
||||
if (loan.loanProduct().isIncludeInBorrowerCycle()) {
|
||||
Integer runningLoancounter = loanToUpdate.getCurrentLoanCounter();
|
||||
if (runningLoancounter > currentLoancounter) {
|
||||
loanToUpdate.updateClientLoanCounter(--runningLoancounter);
|
||||
Integer runningLoanCounter = loanToUpdate.getCurrentLoanCounter();
|
||||
if (runningLoanCounter > currentLoanCounter) {
|
||||
loanToUpdate.updateClientLoanCounter(--runningLoanCounter);
|
||||
}
|
||||
}
|
||||
if (loan.loanProduct().getId().equals(loanToUpdate.loanProduct().getId())) {
|
||||
if (Objects.equals(loan.loanProduct().getId(), loanToUpdate.loanProduct().getId())) {
|
||||
Integer runningLoanProductCounter = loanToUpdate.getLoanProductLoanCounter();
|
||||
if (runningLoanProductCounter > currentLoanProductCounter) {
|
||||
loanToUpdate.updateLoanProductLoanCounter(--runningLoanProductCounter);
|
||||
@@ -2683,21 +2671,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void applyOverdueChargesForLoan(final Long loanId, Collection<OverdueLoanScheduleData> overdueLoanScheduleDatas) {
|
||||
public void applyOverdueChargesForLoan(final Long loanId, Collection<OverdueLoanScheduleData> overdueLoanScheduleDataList) {
|
||||
|
||||
Loan loan = null;
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
|
||||
final List<Long> existingReversedTransactionIds = loan.findExistingReversedTransactionIds();
|
||||
boolean runInterestRecalculation = false;
|
||||
LocalDate recalculateFrom = DateUtils.getBusinessLocalDate();
|
||||
LocalDate lastChargeDate = null;
|
||||
for (final OverdueLoanScheduleData overdueInstallment : overdueLoanScheduleDatas) {
|
||||
for (final OverdueLoanScheduleData overdueInstallment : overdueLoanScheduleDataList) {
|
||||
|
||||
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(overdueInstallment.toString());
|
||||
final JsonCommand command = JsonCommand.from(overdueInstallment.toString(), parsedCommand, this.fromApiJsonHelper, null, null,
|
||||
null, null, null, loanId, null, null, null, null, null, null);
|
||||
LoanOverdueDTO overdueDTO = applyChargeToOverdueLoanInstallment(loanId, overdueInstallment.getChargeId(),
|
||||
overdueInstallment.getPeriodNumber(), command, loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
LoanOverdueDTO overdueDTO = applyChargeToOverdueLoanInstallment(loan, overdueInstallment.getChargeId(),
|
||||
overdueInstallment.getPeriodNumber(), command);
|
||||
loan = overdueDTO.getLoan();
|
||||
runInterestRecalculation = runInterestRecalculation || overdueDTO.isRunInterestRecalculation();
|
||||
if (recalculateFrom.isAfter(overdueDTO.getRecalculateFrom())) {
|
||||
@@ -2735,7 +2723,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
||||
}
|
||||
}
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
}
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
@@ -2745,7 +2732,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanAccountDomainService.recalculateAccruals(loan);
|
||||
}
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanApplyOverdueChargeBusinessEvent(loan));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2772,14 +2758,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
|
||||
public LoanOverdueDTO applyChargeToOverdueLoanInstallment(final Long loanId, final Long loanChargeId, final Integer periodNumber,
|
||||
final JsonCommand command, Loan loan, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
public LoanOverdueDTO applyChargeToOverdueLoanInstallment(final Loan loan, final Long loanChargeId, final Integer periodNumber,
|
||||
final JsonCommand command) {
|
||||
boolean runInterestRecalculation = false;
|
||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(loanChargeId);
|
||||
|
||||
Collection<Integer> frequencyNumbers = loanChargeReadPlatformService.retrieveOverdueInstallmentChargeFrequencyNumber(loanId,
|
||||
chargeDefinition.getId(), periodNumber);
|
||||
Collection<Integer> frequencyNumbers = loanChargeReadPlatformService.retrieveOverdueInstallmentChargeFrequencyNumber(loan,
|
||||
chargeDefinition, periodNumber);
|
||||
|
||||
Integer feeFrequency = chargeDefinition.feeFrequency();
|
||||
final ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
||||
@@ -2787,21 +2772,20 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final Long penaltyWaitPeriodValue = this.configurationDomainService.retrievePenaltyWaitPeriod();
|
||||
final Long penaltyPostingWaitPeriodValue = this.configurationDomainService.retrieveGraceOnPenaltyPostingPeriod();
|
||||
final LocalDate dueDate = command.localDateValueOfParameterNamed("dueDate");
|
||||
Long diff = penaltyWaitPeriodValue + 1 - penaltyPostingWaitPeriodValue;
|
||||
long diff = penaltyWaitPeriodValue + 1 - penaltyPostingWaitPeriodValue;
|
||||
if (diff < 1) {
|
||||
diff = 1L;
|
||||
}
|
||||
LocalDate startDate = dueDate.plusDays(penaltyWaitPeriodValue.intValue() + 1);
|
||||
Integer frequencyNunber = 1;
|
||||
int frequencyNumber = 1;
|
||||
if (feeFrequency == null) {
|
||||
scheduleDates.put(frequencyNunber++, startDate.minusDays(diff));
|
||||
scheduleDates.put(frequencyNumber++, startDate.minusDays(diff));
|
||||
} else {
|
||||
while (!startDate.isAfter(DateUtils.getBusinessLocalDate())) {
|
||||
scheduleDates.put(frequencyNunber++, startDate.minusDays(diff));
|
||||
LocalDate scheduleDate = scheduledDateGenerator.getRepaymentPeriodDate(PeriodFrequencyType.fromInt(feeFrequency),
|
||||
chargeDefinition.feeInterval(), startDate);
|
||||
scheduleDates.put(frequencyNumber++, startDate.minusDays(diff));
|
||||
|
||||
startDate = scheduleDate;
|
||||
startDate = scheduledDateGenerator.getRepaymentPeriodDate(PeriodFrequencyType.fromInt(feeFrequency),
|
||||
chargeDefinition.feeInterval(), startDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2812,12 +2796,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LoanRepaymentScheduleInstallment installment = null;
|
||||
LocalDate lastChargeAppliedDate = dueDate;
|
||||
if (!scheduleDates.isEmpty()) {
|
||||
if (loan == null) {
|
||||
loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||
}
|
||||
installment = loan.fetchRepaymentScheduleInstallment(periodNumber);
|
||||
lastChargeAppliedDate = installment.getDueDate();
|
||||
}
|
||||
@@ -2852,7 +2830,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult undoWriteOff(Long loanId) {
|
||||
final AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -2972,7 +2949,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
if (loan.getDisbursementDetails().size() > loan.loanProduct().maxTrancheCount()) {
|
||||
final String errorMessage = "Number of tranche shouldn't be greter than " + loan.loanProduct().maxTrancheCount();
|
||||
final String errorMessage = "Number of tranche shouldn't be greater than " + loan.loanProduct().maxTrancheCount();
|
||||
throw new ExceedingTrancheCountException(LoanApiConstants.disbursementDataParameterName, errorMessage,
|
||||
loan.loanProduct().maxTrancheCount(), loan.getDisbursementDetails().size());
|
||||
}
|
||||
@@ -2983,16 +2960,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
private CommandProcessingResult processLoanDisbursementDetail(Loan loan, Long loanId, JsonCommand command,
|
||||
LoanDisbursementDetails loanDisbursementDetails) {
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
|
||||
final List<Long> existingReversedTransactionIds = loan.findExistingReversedTransactionIds();
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
AppUser currentUser = getAppUserIfPresent();
|
||||
|
||||
if (command.entityId() != null) {
|
||||
|
||||
@@ -3302,7 +3276,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoLastDisbursalBusinessEvent(loan));
|
||||
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
@@ -3312,7 +3285,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
existingReversedTransactionIds, loan);
|
||||
if (!changes.isEmpty()) {
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
String noteText = null;
|
||||
String noteText;
|
||||
if (command.hasParameter("note")) {
|
||||
noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
@@ -3321,8 +3294,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.getCode(), existingTransactionIds,
|
||||
existingReversedTransactionIds, isAccountTransfer);
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoLastDisbursalBusinessEvent(loan));
|
||||
}
|
||||
@@ -3354,7 +3327,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
for (LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (!loanDisbursementDetails.expectedDisbursementDateAsLocalDate().isAfter(transactionDate)
|
||||
&& loanDisbursementDetails.actualDisbursementDate() == null) {
|
||||
final String defaultUserMessage = "The loan with undisbrsed tranche before foreclosure cannot be foreclosed.";
|
||||
final String defaultUserMessage = "The loan with undisbursed tranche before foreclosure cannot be foreclosed.";
|
||||
throw new LoanForeclosureException("loan.with.undisbursed.tranche.before.foreclosure.cannot.be.foreclosured",
|
||||
defaultUserMessage, transactionDate);
|
||||
}
|
||||
|
||||
+1
-5
@@ -40,9 +40,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
@@ -574,11 +572,9 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
private void postJournalEntries(final SavingsAccount savingsAccount, final Set<Long> existingTransactionIds,
|
||||
final Set<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
|
||||
|
||||
final MonetaryCurrency currency = savingsAccount.getCurrency();
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
|
||||
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(savingsAccount.getCurrency().getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, backdatedTxnsAllowedTill);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
|
||||
}
|
||||
|
||||
+4
-5
@@ -82,7 +82,6 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.apache.fineract.interoperation.domain.InteropIdentifier;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
@@ -1878,13 +1877,13 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> deriveAccountingBridgeData(final CurrencyData currencyData, final Set<Long> existingTransactionIds,
|
||||
public Map<String, Object> deriveAccountingBridgeData(final String currencyCode, final Set<Long> existingTransactionIds,
|
||||
final Set<Long> existingReversedTransactionIds, boolean isAccountTransfer, final boolean backdatedTxnsAllowedTill) {
|
||||
|
||||
final Map<String, Object> accountingBridgeData = new LinkedHashMap<>();
|
||||
accountingBridgeData.put("savingsId", getId());
|
||||
accountingBridgeData.put("savingsProductId", productId());
|
||||
accountingBridgeData.put("currency", currencyData);
|
||||
accountingBridgeData.put("currencyCode", currencyCode);
|
||||
accountingBridgeData.put("officeId", officeId());
|
||||
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnSavingsProduct());
|
||||
accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnSavingsProduct());
|
||||
@@ -1903,9 +1902,9 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
// Adding new transactions to the array
|
||||
for (final SavingsAccountTransaction transaction : trans) {
|
||||
if (transaction.isReversed() && !existingReversedTransactionIds.contains(transaction.getId())) {
|
||||
newSavingsTransactions.add(transaction.toMapData(currencyData));
|
||||
newSavingsTransactions.add(transaction.toMapData(currencyCode));
|
||||
} else if (!existingTransactionIds.contains(transaction.getId())) {
|
||||
newSavingsTransactions.add(transaction.toMapData(currencyData));
|
||||
newSavingsTransactions.add(transaction.toMapData(currencyCode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-6
@@ -32,9 +32,7 @@ import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlat
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.businessevent.domain.savings.transaction.SavingsDepositBusinessEvent;
|
||||
@@ -273,10 +271,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
private void postJournalEntries(final SavingsAccount savingsAccount, final Set<Long> existingTransactionIds,
|
||||
final Set<Long> existingReversedTransactionIds, boolean isAccountTransfer, final boolean backdatedTxnsAllowedTill) {
|
||||
|
||||
final MonetaryCurrency currency = savingsAccount.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
|
||||
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(savingsAccount.getCurrency().getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, backdatedTxnsAllowedTill);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
|
||||
}
|
||||
|
||||
+3
-4
@@ -39,7 +39,6 @@ import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.LocalDateInterval;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
@@ -544,7 +543,7 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
return transactionAmount.isNotEqualTo(amountToCheck);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMapData(final CurrencyData currencyData) {
|
||||
public Map<String, Object> toMapData(final String currencyCode) {
|
||||
final Map<String, Object> thisTransactionData = new LinkedHashMap<>();
|
||||
|
||||
final SavingsAccountTransactionEnumData transactionType = SavingsEnumerations.transactionType(this.typeOf);
|
||||
@@ -552,9 +551,9 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
|
||||
thisTransactionData.put("id", getId());
|
||||
thisTransactionData.put("officeId", this.office.getId());
|
||||
thisTransactionData.put("type", transactionType);
|
||||
thisTransactionData.put("reversed", Boolean.valueOf(isReversed()));
|
||||
thisTransactionData.put("reversed", isReversed());
|
||||
thisTransactionData.put("date", getTransactionLocalDate());
|
||||
thisTransactionData.put("currency", currencyData);
|
||||
thisTransactionData.put("currencyCode", currencyCode);
|
||||
thisTransactionData.put("amount", this.amount);
|
||||
thisTransactionData.put("overdraftAmount", this.overdraftAmount);
|
||||
|
||||
|
||||
+1
-5
@@ -52,9 +52,7 @@ import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavaila
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
@@ -1369,10 +1367,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
private void postJournalEntries(final SavingsAccount savingsAccount, final Set<Long> existingTransactionIds,
|
||||
final Set<Long> existingReversedTransactionIds) {
|
||||
|
||||
final MonetaryCurrency currency = savingsAccount.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(savingsAccount.getCurrency().getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, false);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
|
||||
}
|
||||
|
||||
+1
-5
@@ -64,9 +64,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
|
||||
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
@@ -1544,10 +1542,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
private void postJournalEntries(final SavingsAccount savingsAccount, final Set<Long> existingTransactionIds,
|
||||
final Set<Long> existingReversedTransactionIds, final boolean backdatedTxnsAllowedTill) {
|
||||
|
||||
final MonetaryCurrency currency = savingsAccount.getCurrency();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
|
||||
boolean isAccountTransfer = false;
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(savingsAccount.getCurrency().getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, backdatedTxnsAllowedTill);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
|
||||
}
|
||||
|
||||
+2
-7
@@ -38,8 +38,6 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
|
||||
import org.apache.fineract.portfolio.businessevent.domain.share.ShareAccountApproveBusinessEvent;
|
||||
import org.apache.fineract.portfolio.businessevent.domain.share.ShareAccountCreateBusinessEvent;
|
||||
@@ -130,16 +128,13 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
|
||||
|
||||
private Map<String, Object> populateJournalEntries(final ShareAccount account, final Set<ShareAccountTransaction> transactions) {
|
||||
final Map<String, Object> accountingBridgeData = new HashMap<>();
|
||||
Boolean cashBasedAccounting = account.getShareProduct().getAccountingType().intValue() == 2 ? Boolean.TRUE : Boolean.FALSE;
|
||||
Boolean cashBasedAccounting = account.getShareProduct().getAccountingType() == 2 ? Boolean.TRUE : Boolean.FALSE;
|
||||
accountingBridgeData.put("cashBasedAccountingEnabled", cashBasedAccounting);
|
||||
accountingBridgeData.put("accrualBasedAccountingEnabled", Boolean.FALSE);
|
||||
accountingBridgeData.put("shareAccountId", account.getId());
|
||||
accountingBridgeData.put("shareProductId", account.getShareProduct().getId());
|
||||
accountingBridgeData.put("officeId", account.getOfficeId());
|
||||
MonetaryCurrency currency = account.getCurrency();
|
||||
final CurrencyData currencyData = new CurrencyData(currency.getCode(), "", currency.getDigitsAfterDecimal(),
|
||||
currency.getCurrencyInMultiplesOf(), "", "");
|
||||
accountingBridgeData.put("currency", currencyData);
|
||||
accountingBridgeData.put("currencyCode", account.getCurrency().getCode());
|
||||
final List<Map<String, Object>> newTransactionsMap = new ArrayList<>();
|
||||
accountingBridgeData.put("newTransactions", newTransactionsMap);
|
||||
|
||||
|
||||
+1
-1
@@ -4167,7 +4167,7 @@ public class ClientLoanIntegrationTest {
|
||||
todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant());
|
||||
|
||||
Integer overdueFeeChargeId = ChargesHelper.createCharges(this.requestSpec, this.responseSpec,
|
||||
ChargesHelper.getLoanOverdueFeeJSONWithCalculattionTypePercentage("10"));
|
||||
ChargesHelper.getLoanOverdueFeeJSONWithCalculationTypePercentage("10"));
|
||||
Assertions.assertNotNull(overdueFeeChargeId);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||
|
||||
+68
-14
@@ -230,7 +230,8 @@ public class SchedulerJobsTestResults {
|
||||
final Integer loanProductID = createLoanProduct(null);
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), savingsId.toString());
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), savingsId.toString(),
|
||||
"10 January 2013");
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
@@ -281,7 +282,7 @@ public class SchedulerJobsTestResults {
|
||||
final Integer loanProductID = createLoanProduct(null);
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null);
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2013");
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
@@ -378,7 +379,7 @@ public class SchedulerJobsTestResults {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAccountingRunningBalancesJobOutcome() throws InterruptedException {
|
||||
public void testUpdateAccountingRunningBalancesJobOutcome() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
|
||||
|
||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||
@@ -421,7 +422,7 @@ public class SchedulerJobsTestResults {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLoanArrearsAgingJobOutcome() throws InterruptedException {
|
||||
public void testUpdateLoanArrearsAgingJobOutcome() {
|
||||
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
|
||||
@@ -430,7 +431,7 @@ public class SchedulerJobsTestResults {
|
||||
final Integer loanProductID = createLoanProduct(null);
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null);
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2013");
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
@@ -560,18 +561,18 @@ public class SchedulerJobsTestResults {
|
||||
final Integer loanProductID = createLoanProduct(overdueFeeChargeId.toString());
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null);
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2020");
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
|
||||
|
||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan(AccountTransferTest.LOAN_APPROVAL_DATE, loanID);
|
||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2020", loanID);
|
||||
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
||||
|
||||
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
|
||||
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount(AccountTransferTest.LOAN_APPROVAL_DATE_PLUS_ONE,
|
||||
loanID, JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
|
||||
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
|
||||
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
|
||||
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
||||
|
||||
String JobName = "Apply penalty to overdue loans";
|
||||
@@ -592,6 +593,59 @@ public class SchedulerJobsTestResults {
|
||||
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoanCOBJobOutcome() {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
|
||||
this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
|
||||
Assertions.assertNotNull(clientID);
|
||||
|
||||
Integer overdueFeeChargeId = ChargesHelper.createCharges(requestSpec, responseSpec,
|
||||
ChargesHelper.getLoanOverdueFeeJSONWithCalculationTypePercentage("1"));
|
||||
Assertions.assertNotNull(overdueFeeChargeId);
|
||||
|
||||
final Integer loanProductID = createLoanProduct(overdueFeeChargeId.toString());
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
List<Integer> loanIDs = new ArrayList<>();
|
||||
HashMap loanStatusHashMap;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2020");
|
||||
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
|
||||
|
||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2020", loanID);
|
||||
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
||||
|
||||
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
|
||||
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
|
||||
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
|
||||
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
||||
loanIDs.add(loanID);
|
||||
|
||||
}
|
||||
|
||||
String jobName = "Loan COB";
|
||||
this.schedulerJobHelper.executeAndAwaitJob(jobName);
|
||||
for (Integer loanId : loanIDs) {
|
||||
List<HashMap> repaymentScheduleDataAfter = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
|
||||
loanId);
|
||||
|
||||
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
|
||||
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
|
||||
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(2).get("penaltyChargesDue"),
|
||||
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
|
||||
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(3).get("penaltyChargesDue"),
|
||||
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
|
||||
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(4).get("penaltyChargesDue"),
|
||||
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvoidUnncessaryPenaltyWhenAmountZeroForOverdueLoansJobOutcome() throws InterruptedException {
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
|
||||
@@ -601,13 +655,13 @@ public class SchedulerJobsTestResults {
|
||||
Assertions.assertNotNull(clientID);
|
||||
|
||||
Integer overdueFeeChargeId = ChargesHelper.createCharges(requestSpec, responseSpec,
|
||||
ChargesHelper.getLoanOverdueFeeJSONWithCalculattionTypePercentage("0.000001"));
|
||||
ChargesHelper.getLoanOverdueFeeJSONWithCalculationTypePercentage("0.000001"));
|
||||
Assertions.assertNotNull(overdueFeeChargeId);
|
||||
|
||||
final Integer loanProductID = createLoanProduct(overdueFeeChargeId.toString());
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null);
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2013");
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
@@ -659,7 +713,7 @@ public class SchedulerJobsTestResults {
|
||||
final Integer loanProductID = createLoanProduct(null);
|
||||
Assertions.assertNotNull(loanProductID);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null);
|
||||
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2013");
|
||||
Assertions.assertNotNull(loanID);
|
||||
|
||||
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
@@ -794,7 +848,7 @@ public class SchedulerJobsTestResults {
|
||||
return collateral;
|
||||
}
|
||||
|
||||
private Integer applyForLoanApplication(final String clientID, final String loanProductID, final String savingsID) {
|
||||
private Integer applyForLoanApplication(final String clientID, final String loanProductID, final String savingsID, final String date) {
|
||||
|
||||
List<HashMap> collaterals = new ArrayList<>();
|
||||
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
|
||||
@@ -808,7 +862,7 @@ public class SchedulerJobsTestResults {
|
||||
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("4").withRepaymentEveryAfter("1")
|
||||
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withAmortizationTypeAsEqualInstallments()
|
||||
.withInterestTypeAsDecliningBalance().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
|
||||
.withExpectedDisbursementDate("10 January 2013").withSubmittedOnDate("10 January 2013").withCollaterals(collaterals)
|
||||
.withExpectedDisbursementDate(date).withSubmittedOnDate(date).withCollaterals(collaterals)
|
||||
.build(clientID, loanProductID, savingsID);
|
||||
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||
}
|
||||
|
||||
+1
-1
@@ -302,7 +302,7 @@ public final class ChargesHelper {
|
||||
return chargesCreateJson;
|
||||
}
|
||||
|
||||
public static String getLoanOverdueFeeJSONWithCalculattionTypePercentage(String penaltyPercentageAmount) {
|
||||
public static String getLoanOverdueFeeJSONWithCalculationTypePercentage(String penaltyPercentageAmount) {
|
||||
final HashMap<String, Object> map = populateDefaultsForLoan();
|
||||
map.put("penalty", ChargesHelper.PENALTY);
|
||||
map.put("amount", penaltyPercentageAmount);
|
||||
|
||||
Reference in New Issue
Block a user