Merge branch 'develop' into mysql-5.7

This commit is contained in:
Steve Conrad
2018-10-03 10:59:26 -05:00
committed by GitHub
12 changed files with 297 additions and 79 deletions
@@ -115,10 +115,10 @@ public class ClientEntityImportHandlerTest {
firstClientRow.createCell(ClientEntityConstants.SUBMITTED_ON_COL).setCellValue(submittedDate);
firstClientRow.createCell(ClientEntityConstants.ADDRESS_ENABLED).setCellValue("False");
File directory=new File(System.getProperty("user.home")+"\\Fineract\\bulkimport\\integration_tests\\importhandler\\client") ;
File directory=new File(System.getProperty("user.home")+File.separator+"Fineract"+File.separator+"bulkimport"+File.separator+"integration_tests"+File.separator+"importhandler"+File.separator+"client") ;
if (!directory.exists())
directory.mkdirs();
File file= new File(directory+"\\ClientEntity.xls");
File file= new File(directory+File.separator+"ClientEntity.xls");
OutputStream outputStream=new FileOutputStream(file);
workbook.write(outputStream);
outputStream.close();
@@ -80,27 +80,28 @@ public class LoanImportHandlerTest {
Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
Assert.assertNotNull("Could not create staff",outcome_staff_creation);
// LoanTransactionHelper ltHelper=new LoanTransactionHelper(requestSpec,responseSpec);
// LoanProductTestBuilder loanProductTestBuilder=new LoanProductTestBuilder();
// String jsonLoanProduct=loanProductTestBuilder.build(null);
// Integer outcome_lp_creaion=ltHelper.getLoanProductId(jsonLoanProduct);
// Assert.assertNotNull("Could not create Loan Product" ,outcome_lp_creaion);
// FundsResourceHandler fundsResourceHandler=new FundsResourceHandler();
// String jsonFund="{\n" +
// "\t\"name\": \""+Utils.randomNameGenerator("Fund_Name",9)+"\"\n" +
// "}";
// Integer outcome_fund_creation=fundsResourceHandler.createFund(jsonFund,requestSpec,responseSpec);
// Assert.assertNotNull("Could not create Fund" ,outcome_fund_creation);
// PaymentTypeHelper paymentTypeHelper=new PaymentTypeHelper();
// String name = PaymentTypeHelper.randomNameGenerator("P_T", 5);
// String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 15);
// Boolean isCashPayment = true;
// Integer position = 1;
// Integer outcome_payment_creation= paymentTypeHelper.createPaymentType(requestSpec, responseSpec,name,description,isCashPayment,position);
// Assert.assertNotNull("Could not create payment type" ,outcome_payment_creation);
LoanTransactionHelper loanTransactionHelper=new LoanTransactionHelper(requestSpec,responseSpec);
LoanProductTestBuilder loanProductTestBuilder=new LoanProductTestBuilder();
String jsonLoanProduct=loanProductTestBuilder.build(null);
Integer outcome_lp_creaion=loanTransactionHelper.getLoanProductId(jsonLoanProduct);
Assert.assertNotNull("Could not create Loan Product" ,outcome_lp_creaion);
FundsResourceHandler fundsResourceHandler=new FundsResourceHandler();
String jsonFund="{\n" +
"\t\"name\": \""+Utils.randomNameGenerator("Fund_Name",9)+"\"\n" +
"}";
Integer outcome_fund_creation=fundsResourceHandler.createFund(jsonFund,requestSpec,responseSpec);
Assert.assertNotNull("Could not create Fund" ,outcome_fund_creation);
PaymentTypeHelper paymentTypeHelper=new PaymentTypeHelper();
String name = PaymentTypeHelper.randomNameGenerator("P_T", 5);
String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 15);
Boolean isCashPayment = true;
Integer position = 1;
Integer outcome_payment_creation= paymentTypeHelper.createPaymentType(requestSpec, responseSpec,name,description,isCashPayment,position);
Assert.assertNotNull("Could not create payment type" ,outcome_payment_creation);
Workbook workbook=loanTransactionHelper.getLoanWorkbook("dd MMMM yyyy");
//insert dummy data into loan Sheet
@@ -127,7 +128,7 @@ public class LoanImportHandlerTest {
firstLoanRow.createCell(LoanConstants.NO_OF_REPAYMENTS_COL).setCellValue(loanProductSheet.getRow(1).getCell(6).getNumericCellValue());
firstLoanRow.createCell(LoanConstants.REPAID_EVERY_COL).setCellValue(loanProductSheet.getRow(1).getCell(9).getNumericCellValue());
firstLoanRow.createCell(LoanConstants.REPAID_EVERY_FREQUENCY_COL).setCellValue(loanProductSheet.getRow(1).getCell(10).getStringCellValue());
firstLoanRow.createCell(LoanConstants.LOAN_TERM_COL).setCellValue(loanProductSheet.getRow(1).getCell(8).getNumericCellValue());
firstLoanRow.createCell(LoanConstants.LOAN_TERM_COL).setCellValue(60);
firstLoanRow.createCell(LoanConstants.LOAN_TERM_FREQUENCY_COL).setCellValue(loanProductSheet.getRow(1).getCell(10).getStringCellValue());
firstLoanRow.createCell(LoanConstants.NOMINAL_INTEREST_RATE_COL).setCellValue(loanProductSheet.getRow(1).getCell(11).getNumericCellValue());
firstLoanRow.createCell(LoanConstants.NOMINAL_INTEREST_RATE_FREQUENCY_COL).setCellValue(loanProductSheet.getRow(1).getCell(14).getStringCellValue());
@@ -144,10 +145,12 @@ public class LoanImportHandlerTest {
firstLoanRow.createCell(LoanConstants.LAST_REPAYMENT_DATE_COL).setCellValue(date);
firstLoanRow.createCell(LoanConstants.REPAYMENT_TYPE_COL).setCellValue(extrasSheet.getRow(1).getCell(3).getStringCellValue());
File directory=new File(System.getProperty("user.home")+"\\Fineract\\bulkimport\\integration_tests\\importhandler\\loan") ;
String currentdirectory = new File("").getAbsolutePath();
File directory=new File(currentdirectory+File.separator+"src"+File.separator+"integrationTest"+File.separator+
"resources"+File.separator+"bulkimport"+File.separator+"importhandler"+File.separator+"loan") ;
if (!directory.exists())
directory.mkdirs();
File file= new File(directory+"\\Loan.xls");
File file= new File(directory+File.separator+"Loan.xls");
OutputStream outputStream=new FileOutputStream(file);
workbook.write(outputStream);
outputStream.close();
@@ -157,7 +160,7 @@ public class LoanImportHandlerTest {
Assert.assertNotNull(importDocumentId);
//Wait for the creation of output excel
Thread.sleep(3000);
Thread.sleep(10000);
//check status column of output excel
String location=loanTransactionHelper.getOutputTemplateLocation(importDocumentId);
@@ -74,11 +74,11 @@ public class OfficeImportHandlerTest {
firstOfficeRow.createCell(OfficeConstants.OPENED_ON_COL).setCellValue(date);
String currentdirectory = new File("").getAbsolutePath();
File directory=new File(currentdirectory+"\\src\\integrationTest\\" +
"resources\\bulkimport\\importhandler\\office");
File directory=new File(currentdirectory+File.separator+"src"+File.separator+"integrationTest"+File.separator+
"resources"+File.separator+"bulkimport"+File.separator+"importhandler"+File.separator+"office");
if (!directory.exists())
directory.mkdirs();
File file= new File(directory+"\\Office.xls");
File file= new File(directory+File.separator+"Office.xls");
OutputStream outputStream=new FileOutputStream(file);
workbook.write(outputStream);
outputStream.close();
@@ -118,17 +118,19 @@ public class SavingsImportHandlerTest {
firstSavingsRow.createCell(SavingsConstants.INTEREST_POSTING_PERIOD_COL).setCellValue(savingsProductSheet.getRow(1).getCell(4).getStringCellValue());
firstSavingsRow.createCell(SavingsConstants.INTEREST_CALCULATION_COL).setCellValue(savingsProductSheet.getRow(1).getCell(5).getStringCellValue());
firstSavingsRow.createCell(SavingsConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL).setCellValue(savingsProductSheet.getRow(1).getCell(6).getStringCellValue());
firstSavingsRow.createCell(SavingsConstants.MIN_OPENING_BALANCE_COL).setCellValue(savingsProductSheet.getRow(1).getCell(7).getNumericCellValue());
firstSavingsRow.createCell(SavingsConstants.LOCKIN_PERIOD_COL).setCellValue(savingsProductSheet.getRow(1).getCell(8).getNumericCellValue());
firstSavingsRow.createCell(SavingsConstants.LOCKIN_PERIOD_FREQUENCY_COL).setCellValue(savingsProductSheet.getRow(1).getCell(9).getStringCellValue());
firstSavingsRow.createCell(SavingsConstants.MIN_OPENING_BALANCE_COL).setCellValue(1000.0);
firstSavingsRow.createCell(SavingsConstants.LOCKIN_PERIOD_COL).setCellValue(1);
firstSavingsRow.createCell(SavingsConstants.LOCKIN_PERIOD_FREQUENCY_COL).setCellValue("Weeks");
firstSavingsRow.createCell(SavingsConstants.APPLY_WITHDRAWAL_FEE_FOR_TRANSFERS).setCellValue("False");
firstSavingsRow.createCell(SavingsConstants.ALLOW_OVER_DRAFT_COL).setCellValue("False");
firstSavingsRow.createCell(SavingsConstants.OVER_DRAFT_LIMIT_COL).setCellValue(savingsProductSheet.getRow(1).getCell(15).getNumericCellValue());
File directory=new File(System.getProperty("user.home")+"\\Fineract\\bulkimport\\integration_tests\\importhandler\\savings") ;
String currentdirectory = new File("").getAbsolutePath();
File directory=new File(currentdirectory+File.separator+"src"+File.separator+"integrationTest"+File.separator+
"resources"+File.separator+"bulkimport"+File.separator+"importhandler"+File.separator+"savings") ;
if (!directory.exists())
directory.mkdirs();
File file= new File(directory+"\\Savings.xls");
File file= new File(directory+File.separator+"Savings.xls");
OutputStream outputStream=new FileOutputStream(file);
workbook.write(outputStream);
outputStream.close();
@@ -138,7 +140,7 @@ public class SavingsImportHandlerTest {
Assert.assertNotNull(importDocumentId);
//Wait for the creation of output excel
Thread.sleep(3000);
Thread.sleep(10000);
//check status column of output excel
String location=savingsAccountHelper.getOutputTemplateLocation(importDocumentId);
@@ -1187,8 +1187,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
sql = sql + "select * from `" + dataTableName + "` where id = " + id;
}
this.columnValidator.validateSqlInjection(sql, order);
if (order != null) {
if (StringUtils.isNotBlank(order)) {
this.columnValidator.validateSqlInjection(sql, order);
sql = sql + " order by " + order;
}
@@ -29,27 +29,34 @@ public class AccountSummaryCollectionData {
private final Collection<LoanAccountSummaryData> loanAccounts;
private final Collection<SavingsAccountSummaryData> savingsAccounts;
private final Collection<ShareAccountSummaryData> shareAccounts ;
private final Collection<GuarantorAccountSummaryData> guarantorAccounts;
private final Collection<LoanAccountSummaryData> memberLoanAccounts;
private final Collection<SavingsAccountSummaryData> memberSavingsAccounts;
private final Collection<GuarantorAccountSummaryData> memberGuarantorAccounts;
public AccountSummaryCollectionData(final Collection<LoanAccountSummaryData> loanAccounts,
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<ShareAccountSummaryData> shareAccounts) {
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<ShareAccountSummaryData> shareAccounts,
final Collection<GuarantorAccountSummaryData> guarantorAccounts) {
this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts);
this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts);
this.shareAccounts = defaultShareAccountsIfEmpty(shareAccounts) ;
this.guarantorAccounts = guarantorAccounts;
this.memberLoanAccounts = null;
this.memberSavingsAccounts = null;
this.memberGuarantorAccounts = null;
}
public AccountSummaryCollectionData(final Collection<LoanAccountSummaryData> loanAccounts,
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<LoanAccountSummaryData> memberLoanAccounts,
final Collection<SavingsAccountSummaryData> memberSavingsAccounts) {
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<GuarantorAccountSummaryData> guarantorAccounts, final Collection<LoanAccountSummaryData> memberLoanAccounts,
final Collection<SavingsAccountSummaryData> memberSavingsAccounts, final Collection<GuarantorAccountSummaryData> memberGuarantorAccounts) {
this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts);
this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts);
this.guarantorAccounts = guarantorAccounts;
this.shareAccounts = null ;
this.memberLoanAccounts = defaultLoanAccountsIfEmpty(memberLoanAccounts);
this.memberSavingsAccounts = defaultSavingsAccountsIfEmpty(memberSavingsAccounts);
this.memberGuarantorAccounts = defaultGuarantorAccountsIfEmpty(memberGuarantorAccounts);
}
private Collection<LoanAccountSummaryData> defaultLoanAccountsIfEmpty(final Collection<LoanAccountSummaryData> collection) {
@@ -76,4 +83,11 @@ public class AccountSummaryCollectionData {
return returnCollection;
}
private Collection<GuarantorAccountSummaryData> defaultGuarantorAccountsIfEmpty(final Collection<GuarantorAccountSummaryData> collection) {
Collection<GuarantorAccountSummaryData> returnCollection = null;
if (collection != null && !collection.isEmpty()) {
returnCollection = collection;
}
return returnCollection;
}
}
@@ -0,0 +1,70 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.accountdetails.data;
import java.math.BigDecimal;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.portfolio.loanaccount.data.LoanApplicationTimelineData;
import org.apache.fineract.portfolio.loanaccount.data.LoanStatusEnumData;
/**
* Immutable data object for loan accounts.
*/
@SuppressWarnings("unused")
public class GuarantorAccountSummaryData {
private final Long id;
private final String accountNo;
private final String externalId;
private final Long productId;
private final String productName;
private final String shortProductName;
private final LoanStatusEnumData status;
private final EnumOptionData loanType;
private final Integer loanCycle;
private final Boolean inArrears;
private final BigDecimal originalLoan;
private final BigDecimal loanBalance;
private final BigDecimal amountPaid;
private final Boolean isActive;
private final String relationship;
private final BigDecimal onHoldAmount;
public GuarantorAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
final String loanProductName, final String shortLoanProductName, final LoanStatusEnumData loanStatus, final EnumOptionData loanType, final Integer loanCycle,
final Boolean inArrears,final BigDecimal originalLoan,final BigDecimal loanBalance,final BigDecimal amountPaid,
final Boolean isActive, final String relationship, final BigDecimal onHoldAmount) {
this.id = id;
this.accountNo = accountNo;
this.externalId = externalId;
this.productId = productId;
this.productName = loanProductName;
this.shortProductName = shortLoanProductName;
this.status = loanStatus;
this.loanType = loanType;
this.loanCycle = loanCycle;
this.inArrears = inArrears;
this.loanBalance = loanBalance;
this.originalLoan = originalLoan;
this.amountPaid = amountPaid;
this.isActive = isActive;
this.relationship = relationship;
this.onHoldAmount = onHoldAmount;
}
}
@@ -30,6 +30,7 @@ import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
import org.apache.fineract.portfolio.accountdetails.data.GuarantorAccountSummaryData;
import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
import org.apache.fineract.portfolio.accountdetails.data.SavingsAccountSummaryData;
import org.apache.fineract.portfolio.accountdetails.data.ShareAccountSummaryData;
@@ -75,10 +76,14 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
this.clientReadPlatformService.retrieveOne(clientId);
final String loanwhereClause = " where l.client_id = ?";
final String savingswhereClause = " where sa.client_id = ? order by sa.status_enum ASC, sa.account_no ASC";
final String guarantorWhereClause = " where g.entity_id = ? and g.is_active = 1 order by l.account_no ASC";
final List<LoanAccountSummaryData> loanAccounts = retrieveLoanAccountDetails(loanwhereClause, new Object[] { clientId });
final List<SavingsAccountSummaryData> savingsAccounts = retrieveAccountDetails(savingswhereClause, new Object[] { clientId });
final List<ShareAccountSummaryData> shareAccounts = retrieveShareAccountDetails(clientId) ;
return new AccountSummaryCollectionData(loanAccounts, savingsAccounts, shareAccounts);
final List<GuarantorAccountSummaryData> guarantorloanAccounts = retrieveGuarantorLoanAccountDetails(
guarantorWhereClause, new Object[] { clientId });
return new AccountSummaryCollectionData(loanAccounts, savingsAccounts, shareAccounts, guarantorloanAccounts);
}
@Override
@@ -89,14 +94,21 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
final String loanWhereClauseForMembers = " where l.group_id = ? and l.client_id is not null";
final String savingswhereClauseForGroup = " where sa.group_id = ? and sa.client_id is null order by sa.status_enum ASC, sa.account_no ASC";
final String savingswhereClauseForMembers = " where sa.group_id = ? and sa.client_id is not null order by sa.status_enum ASC, sa.account_no ASC";
final String guarantorWhereClauseForGroup = " where l.group_id = ? and l.client_id is null and g.is_active = 1 order by l.account_no ASC";
final String guarantorWhereClauseForMembers = " where l.group_id = ? and l.client_id is not null and g.is_active = 1 order by l.account_no ASC";
final List<LoanAccountSummaryData> groupLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroup, new Object[] { groupId });
final List<SavingsAccountSummaryData> groupSavingsAccounts = retrieveAccountDetails(savingswhereClauseForGroup,
new Object[] { groupId });
final List<GuarantorAccountSummaryData> groupGuarantorloanAccounts = retrieveGuarantorLoanAccountDetails(
guarantorWhereClauseForGroup, new Object[] { groupId });
final List<LoanAccountSummaryData> memberLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForMembers,
new Object[] { groupId });
final List<SavingsAccountSummaryData> memberSavingsAccounts = retrieveAccountDetails(savingswhereClauseForMembers,
new Object[] { groupId });
return new AccountSummaryCollectionData(groupLoanAccounts, groupSavingsAccounts, memberLoanAccounts, memberSavingsAccounts);
final List<GuarantorAccountSummaryData> memberGuarantorloanAccounts = retrieveGuarantorLoanAccountDetails(
guarantorWhereClauseForMembers, new Object[] { groupId });
return new AccountSummaryCollectionData(groupLoanAccounts, groupSavingsAccounts, groupGuarantorloanAccounts, memberLoanAccounts, memberSavingsAccounts, memberGuarantorloanAccounts);
}
@Override
@@ -144,6 +156,14 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
return this.jdbcTemplate.query(query, mapper, new Object [] {clientId});
}
private List<GuarantorAccountSummaryData> retrieveGuarantorLoanAccountDetails(
final String loanwhereClause, final Object[] inputs) {
final GuarantorLoanAccountSummaryDataMapper rm = new GuarantorLoanAccountSummaryDataMapper();
final String sql = "select " + rm.guarantorLoanAccountSummarySchema()
+ loanwhereClause;
return this.jdbcTemplate.query(sql, rm, inputs);
}
private final static class ShareAccountSummaryDataMapper implements RowMapper<ShareAccountSummaryData> {
private final String schema ;
@@ -493,6 +513,97 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
return new LoanAccountSummaryData(id, accountNo, externalId, productId, loanProductName, shortLoanProductName, loanStatus, loanType, loanCycle,
timeline, inArrears,originalLoan,loanBalance,amountPaid);
}
}
private static final class GuarantorLoanAccountSummaryDataMapper implements
RowMapper<GuarantorAccountSummaryData> {
public String guarantorLoanAccountSummarySchema() {
final StringBuilder accountsSummary = new StringBuilder(
"l.id as id, l.account_no as accountNo, l.external_id as externalId,");
accountsSummary
.append(" l.product_id as productId, lp.name as productName, lp.short_name as shortProductName,")
.append(" l.loan_status_id as statusId, l.loan_type_enum as loanType,")
.append("l.principal_disbursed_derived as originalLoan,")
.append("l.total_outstanding_derived as loanBalance,")
.append("l.total_repayment_derived as amountPaid,")
.append(" l.loan_product_counter as loanCycle,")
.append(" l.submittedon_date as submittedOnDate,")
.append(" l.rejectedon_date as rejectedOnDate,")
.append(" l.withdrawnon_date as withdrawnOnDate,")
.append(" l.approvedon_date as approvedOnDate,")
.append(" l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate,")
.append(" l.closedon_date as closedOnDate,")
.append(" la.overdue_since_date_derived as overdueSinceDate,")
.append(" l.writtenoffon_date as writtenOffOnDate, l.expected_maturedon_date as expectedMaturityDate,")
.append(" g.is_active as isActive,")
.append(" cv.code_value as relationship,")
.append(" sa.on_hold_funds_derived")
.append(" from m_loan l ")
.append(" join m_guarantor as g on g.loan_id = l.id ")
.append(" join m_client as c on c.id = g.entity_id ")
.append(" LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id")
.append(" left join m_loan_arrears_aging la on la.loan_id = l.id")
.append(" left join m_code_value cv ON cv.id = g.client_reln_cv_id")
.append(" left join m_savings_account sa on sa.client_id = c.id")
;
return accountsSummary.toString();
}
@Override
public GuarantorAccountSummaryData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String accountNo = rs.getString("accountNo");
final String externalId = rs.getString("externalId");
final Long productId = JdbcSupport.getLong(rs, "productId");
final String loanProductName = rs.getString("productName");
final String shortLoanProductName = rs
.getString("shortProductName");
final Integer loanStatusId = JdbcSupport.getInteger(rs, "statusId");
final LoanStatusEnumData loanStatus = LoanEnumerations
.status(loanStatusId);
final Integer loanTypeId = JdbcSupport.getInteger(rs, "loanType");
final EnumOptionData loanType = AccountEnumerations
.loanType(loanTypeId);
final Integer loanCycle = JdbcSupport.getInteger(rs, "loanCycle");
final BigDecimal originalLoan = JdbcSupport
.getBigDecimalDefaultToNullIfZero(rs, "originalLoan");
final BigDecimal loanBalance = JdbcSupport
.getBigDecimalDefaultToNullIfZero(rs, "loanBalance");
final BigDecimal amountPaid = JdbcSupport
.getBigDecimalDefaultToNullIfZero(rs, "amountPaid");
final BigDecimal onHoldAmount = JdbcSupport
.getBigDecimalDefaultToNullIfZero(rs,
"on_hold_funds_derived");
final LocalDate overdueSinceDate = JdbcSupport.getLocalDate(rs,
"overdueSinceDate");
Boolean inArrears = true;
if (overdueSinceDate == null) {
inArrears = false;
}
final Boolean isActive = rs.getBoolean("isActive");
final String relationship = rs.getString("relationship");
return new GuarantorAccountSummaryData(id, accountNo, externalId,
productId, loanProductName, shortLoanProductName,
loanStatus, loanType, loanCycle, inArrears, originalLoan,
loanBalance, amountPaid, isActive, relationship,
onHoldAmount);
}
}
}
}
@@ -108,7 +108,7 @@ public final class Group extends AbstractPersistableCustom<Long> {
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "parent_id")
private final List<Group> groupMembers = new LinkedList<>();
private List<Group> groupMembers = new LinkedList<>();
@ManyToMany
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "group_id"), inverseJoinColumns = @JoinColumn(name = "client_id"))
@@ -744,4 +744,10 @@ public final class Group extends AbstractPersistableCustom<Long> {
this.accountNumber = accountIdentifier;
this.accountNumberRequiresAutoGeneration = false;
}
public void setGroupMembers(List<Group> groupMembers) {
this.groupMembers = groupMembers;
}
}
@@ -148,6 +148,16 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper {
"The parameter loanTermFrequency is less than the suggest loan term as indicated by numberOfRepayments and repaymentEvery.",
"loanTermFrequency", loanTermFrequency, numberOfRepayments, repaymentEvery);
dataValidationErrors.add(error);
} else {
if (loanTermFrequency.intValue() > suggestsedLoanTerm) {
final ApiParameterError error = ApiParameterError
.parameterError(
"validation.msg.loan.loanTermFrequency.greater.than.repayment.structure.suggests",
"The parameter loanTermFrequency is greater than the suggested loan term as indicated by numberOfRepayments and repaymentEvery.",
"loanTermFrequency", loanTermFrequency, numberOfRepayments, repaymentEvery);
dataValidationErrors.add(error);
}
}
}
}
@@ -88,7 +88,9 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanSchedu
import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper;
import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationTransitionApiJsonValidator;
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
import org.apache.fineract.portfolio.loanproduct.domain.*;
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.apache.fineract.portfolio.loanproduct.serialization.LoanProductDataValidator;
@@ -104,6 +106,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@@ -147,6 +150,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
private final FineractEntityToEntityMappingRepository repository;
private final FineractEntityRelationRepository fineractEntityRelationRepository;
private final LoanProductReadPlatformService loanProductReadPlatformService;
@Autowired
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
@@ -169,7 +173,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final LoanScheduleAssembler loanScheduleAssembler, final LoanUtilService loanUtilService,
final CalendarReadPlatformService calendarReadPlatformService, final GlobalConfigurationRepositoryWrapper globalConfigurationRepository,
final FineractEntityToEntityMappingRepository repository, final FineractEntityRelationRepository fineractEntityRelationRepository,
final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService) {
final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, final LoanProductReadPlatformService loanProductReadPlatformService) {
this.context = context;
this.fromJsonHelper = fromJsonHelper;
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
@@ -204,6 +208,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.globalConfigurationRepository = globalConfigurationRepository;
this.repository = repository;
this.fineractEntityRelationRepository = fineractEntityRelationRepository;
this.loanProductReadPlatformService = loanProductReadPlatformService;
}
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -256,6 +262,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final Loan newLoanApplication = this.loanAssembler.assembleFrom(command, currentUser);
checkForProductMixRestrictions(newLoanApplication);
validateSubmittedOnDate(newLoanApplication);
final LoanProductRelatedDetail productRelatedDetail = newLoanApplication.repaymentScheduleDetail();
@@ -415,6 +423,33 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
}
}
public void checkForProductMixRestrictions(final Loan loan) {
final List<Long> activeLoansLoanProductIds;
final Long productId = loan.loanProduct().getId();
if (loan.isGroupLoan()) {
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByGroup(loan.getGroupId(),
LoanStatus.ACTIVE.getValue());
} else {
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByClient(loan.getClientId(),
LoanStatus.ACTIVE.getValue());
}
checkForProductMixRestrictions(activeLoansLoanProductIds, productId, loan.loanProduct().productName());
}
private void checkForProductMixRestrictions(final List<Long> activeLoansLoanProductIds, final Long productId, final String productName) {
if (!CollectionUtils.isEmpty(activeLoansLoanProductIds)) {
final Collection<LoanProductData> restrictedPrdouctsList = this.loanProductReadPlatformService
.retrieveRestrictedProductsForMix(productId);
for (final LoanProductData restrictedProduct : restrictedPrdouctsList) {
if (activeLoansLoanProductIds.contains(restrictedProduct.getId())) { throw new GeneralPlatformDomainRuleException("error.msg.loan.applied.or.to.be.disbursed.can.not.co-exist.with.the.loan.already.active.to.this.client", "This loan could not be applied/disbursed as the loan and `" + restrictedProduct + "` are not allowed to co-exist"); }
}
}
}
private void updateProductRelatedDetails(LoanProductRelatedDetail productRelatedDetail, Loan loan) {
final Boolean amortization = loan.loanProduct().getLoanProductConfigurableAttributes().getAmortizationBoolean();
final Boolean arrearsTolerance = loan.loanProduct().getLoanProductConfigurableAttributes().getArrearsToleranceBoolean();
@@ -102,11 +102,9 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationCo
import org.apache.fineract.portfolio.loanaccount.serialization.LoanEventApiJsonValidator;
import org.apache.fineract.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
import org.apache.fineract.portfolio.loanproduct.data.LoanOverdueDTO;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
import org.apache.fineract.portfolio.note.domain.Note;
import org.apache.fineract.portfolio.note.domain.NoteRepository;
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
@@ -151,7 +149,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private final HolidayRepositoryWrapper holidayRepository;
private final ConfigurationDomainService configurationDomainService;
private final WorkingDaysRepositoryWrapper workingDaysRepository;
private final LoanProductReadPlatformService loanProductReadPlatformService;
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService;
@@ -186,7 +183,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final CalendarInstanceRepository calendarInstanceRepository,
final PaymentDetailWritePlatformService paymentDetailWritePlatformService, final HolidayRepositoryWrapper holidayRepository,
final ConfigurationDomainService configurationDomainService, final WorkingDaysRepositoryWrapper workingDaysRepository,
final LoanProductReadPlatformService loanProductReadPlatformService,
final AccountTransfersWritePlatformService accountTransfersWritePlatformService,
final AccountTransfersReadPlatformService accountTransfersReadPlatformService,
final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService,
@@ -222,7 +218,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.holidayRepository = holidayRepository;
this.configurationDomainService = configurationDomainService;
this.workingDaysRepository = workingDaysRepository;
this.loanProductReadPlatformService = loanProductReadPlatformService;
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
this.accountTransfersReadPlatformService = accountTransfersReadPlatformService;
this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService;
@@ -276,8 +271,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, EntityTables.LOAN.getName(),
StatusEnum.DISBURSE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId());
// check for product mix validations
checkForProductMixRestrictions(loan);
LocalDate recalculateFrom = null;
if(!loan.isMultiDisburmentLoan()){
@@ -2267,32 +2260,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.holidayRepository.save(holidays);
}
private void checkForProductMixRestrictions(final Loan loan) {
final List<Long> activeLoansLoanProductIds;
final Long productId = loan.loanProduct().getId();
if (loan.isGroupLoan()) {
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByGroup(loan.getGroupId(),
LoanStatus.ACTIVE.getValue());
} else {
activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByClient(loan.getClientId(),
LoanStatus.ACTIVE.getValue());
}
checkForProductMixRestrictions(activeLoansLoanProductIds, productId, loan.loanProduct().productName());
}
private void checkForProductMixRestrictions(final List<Long> activeLoansLoanProductIds, final Long productId, final String productName) {
if (!CollectionUtils.isEmpty(activeLoansLoanProductIds)) {
final Collection<LoanProductData> restrictedPrdouctsList = this.loanProductReadPlatformService
.retrieveRestrictedProductsForMix(productId);
for (final LoanProductData restrictedProduct : restrictedPrdouctsList) {
if (activeLoansLoanProductIds.contains(restrictedProduct.getId())) { throw new LoanDisbursalException(productName,
restrictedProduct.getName()); }
}
}
}
private void checkClientOrGroupActive(final Loan loan) {
final Client client = loan.client();