Merge pull request #1770 from BLasan/collateral-module

Feat: Collateral module
This commit is contained in:
Manthan Surkar
2021-09-03 19:54:00 +05:30
committed by GitHub
113 changed files with 5780 additions and 325 deletions
@@ -482,6 +482,14 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder createCollateral() {
this.actionName = "CREATE";
this.entityId = null;
this.entityName = "COLLATERAL_PRODUCT";
this.href = "/collateral-product";
return this;
}
public CommandWrapperBuilder updateCharge(final Long chargeId) {
this.actionName = "UPDATE";
this.entityName = "CHARGE";
@@ -1823,6 +1831,32 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder updateCollateralProduct(final Long collateralId) {
this.actionName = "UPDATE";
this.entityName = "COLLATERAL_PRODUCT";
this.entityId = collateralId;
this.href = "/collateral-management/" + collateralId;
return this;
}
public CommandWrapperBuilder updateClientCollateralProduct(final Long clientId, final Long collateralId) {
this.actionName = "UPDATE";
this.entityName = "CLIENT_COLLATERAL_PRODUCT";
this.entityId = collateralId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/collateral/" + collateralId;
return this;
}
public CommandWrapperBuilder deleteLoanCollateral(final Long loanId, final Long collateralId) {
this.actionName = "DELETE";
this.entityName = "LOAN_COLLATERAL_PRODUCT";
this.entityId = collateralId;
this.loanId = loanId;
this.href = "/loans/" + loanId + "/collateral/" + collateralId;
return this;
}
public CommandWrapperBuilder deleteCollateral(final Long loanId, final Long collateralId) {
this.actionName = "DELETE";
this.entityName = "COLLATERAL";
@@ -1832,6 +1866,31 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder deleteCollateralProduct(final Long collateralId) {
this.actionName = "DELETE";
this.entityName = "COLLATERAL_PRODUCT";
this.entityId = collateralId;
this.href = "/collateral-management/" + collateralId;
return this;
}
public CommandWrapperBuilder deleteClientCollateralProduct(final Long collateralId, final Long clientId) {
this.actionName = "DELETE";
this.entityName = "CLIENT_COLLATERAL_PRODUCT";
this.entityId = collateralId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/collateral-management/" + collateralId;
return this;
}
public CommandWrapperBuilder addClientCollateralProduct(final Long clientId) {
this.actionName = "CREATE";
this.entityName = "CLIENT_COLLATERAL_PRODUCT";
this.clientId = clientId;
this.href = "/clients/" + clientId + "/collateral-management";
return this;
}
public CommandWrapperBuilder updateCollectionSheet(final Long groupId) {
this.actionName = "UPDATE";
this.entityName = "COLLECTIONSHEET";
@@ -71,6 +71,8 @@ public final class LoanConstants {
public static final int LOOKUP_CLIENT_EXTERNAL_ID = 44;// AS
public static final int LOOKUP_ACTIVATION_DATE_COL = 45;// AT
public static final int LINK_ACCOUNT_ID = 46;// AU
public static final int LOAN_COLLATERAL_ID = 47;
public static final int LOAN_COLLATERAL_QUANTITY = 48;
public static final String LOAN_TYPE_INDIVIDUAL = "Individual";
public static final String LOAN_TYPE_GROUP = "Group";
@@ -43,7 +43,9 @@ import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData;
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
@@ -270,6 +272,8 @@ public class LoanImportHandler implements ImportHandler {
Long charge1 = ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row);
Long charge2 = ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row);
Long collateralId = ImportHandlerUtils.readAsLong(LoanConstants.LOAN_COLLATERAL_ID, row);
Long groupId = ImportHandlerUtils.readAsLong(LoanConstants.GROUP_ID, row);
String linkAccountId = ImportHandlerUtils.readAsString(LoanConstants.LINK_ACCOUNT_ID, row);
@@ -295,6 +299,19 @@ public class LoanImportHandler implements ImportHandler {
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row), null));
}
}
List<LoanCollateralManagementData> loanCollateralManagementData = new ArrayList<>();
if (collateralId != null) {
if (ImportHandlerUtils.readAsDouble(LoanConstants.LOAN_COLLATERAL_QUANTITY, row) != null) {
loanCollateralManagementData.add(new LoanCollateralManagementData(collateralId,
BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.LOAN_COLLATERAL_QUANTITY, row)), null, null,
null));
} else {
throw new InvalidAmountOfCollateralQuantity(null);
}
}
statuses.add(status);
if (loanType != null) {
if (loanType.equals("individual")) {
@@ -305,7 +322,7 @@ public class LoanImportHandler implements ImportHandler {
nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum,
arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, null, charges, linkAccountId, locale,
dateFormat);
dateFormat, loanCollateralManagementData);
} else if (loanType.equals("jlg")) {
Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME),
clientOrGroupName);
@@ -314,7 +331,7 @@ public class LoanImportHandler implements ImportHandler {
nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum,
arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, groupId, charges, linkAccountId, locale,
dateFormat);
dateFormat, null);
} else {
Long groupIdforGroupLoan = ImportHandlerUtils
.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME), clientOrGroupName);
@@ -18,12 +18,17 @@
*/
package org.apache.fineract.organisation.monetary.domain;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.office.domain.OrganisationCurrency;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
@Entity
@Table(name = "m_currency")
@@ -47,6 +52,9 @@ public class ApplicationCurrency extends AbstractPersistableCustom {
@Column(name = "display_symbol", nullable = true, length = 10)
private String displaySymbol;
@OneToMany(mappedBy = "currency", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private Collection<CollateralManagementDomain> collateralManagementData;
protected ApplicationCurrency() {
this.code = null;
this.name = null;
@@ -95,6 +103,10 @@ public class ApplicationCurrency extends AbstractPersistableCustom {
return this.displaySymbol;
}
public Collection<CollateralManagementDomain> getCollateralManagementData() {
return this.collateralManagementData;
}
public CurrencyData toData() {
return new CurrencyData(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.displaySymbol, this.nameCode);
}
@@ -106,4 +118,8 @@ public class ApplicationCurrency extends AbstractPersistableCustom {
public OrganisationCurrency toOrganisationCurrency() {
return new OrganisationCurrency(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.nameCode, this.displaySymbol);
}
public void setCode(final String code) {
this.code = code;
}
}
@@ -0,0 +1,82 @@
/**
* 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.client.data;
import java.io.Serializable;
import java.math.BigDecimal;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
public final class ClientCollateralManagementData implements Serializable {
private final BigDecimal quantity;
private final Long id;
private final BigDecimal pctToBase;
private final BigDecimal unitPrice;
private final BigDecimal total;
private final BigDecimal totalCollateral;
private final String name;
private ClientCollateralManagementData(final BigDecimal quantity, final Long id, final BigDecimal pctToBase, final BigDecimal unitPrice,
final BigDecimal total, final BigDecimal totalCollateral, final String name) {
this.id = id;
this.pctToBase = pctToBase;
this.total = total;
this.totalCollateral = totalCollateral;
this.unitPrice = unitPrice;
this.quantity = quantity;
this.name = name;
}
public static ClientCollateralManagementData setCollateralValues(final ClientCollateralManagement clientCollateralManagements,
final BigDecimal total, final BigDecimal totalCollateral) {
return new ClientCollateralManagementData(clientCollateralManagements.getQuantity(), clientCollateralManagements.getId(),
clientCollateralManagements.getCollaterals().getPctToBase(), clientCollateralManagements.getCollaterals().getBasePrice(),
total, totalCollateral, clientCollateralManagements.getCollaterals().getName());
}
public BigDecimal getQuantity() {
return this.quantity;
}
public BigDecimal getTotal() {
return this.total;
}
public BigDecimal getPctToBase() {
return this.pctToBase;
}
public BigDecimal getTotalCollateral() {
return this.totalCollateral;
}
public BigDecimal getUnitPrice() {
return this.unitPrice;
}
public Long getId() {
return this.id;
}
}
@@ -22,6 +22,7 @@ import java.io.Serializable;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -32,6 +33,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.staff.data.StaffData;
import org.apache.fineract.portfolio.address.data.AddressData;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
@@ -81,6 +83,7 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
private final Long savingsAccountId;
private final EnumOptionData legalForm;
private final Set<ClientCollateralManagementData> clientCollateralManagements;
// associations
private final Collection<GroupGeneralData> groups;
@@ -201,6 +204,7 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
this.datatables = null;
this.familyMemberOptions = null;
this.emailAddress = null;
this.clientCollateralManagements = null;
}
public Integer getRowIndex() {
@@ -258,18 +262,19 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
final EnumOptionData legalForm = null;
final Boolean isStaff = false;
final ClientNonPersonData clientNonPersonDetails = null;
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, joinedDate, imageId,
staffId, staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions,
savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification,
clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions,
clientNonPersonDetails, clientLegalFormOptions, familyMemberOptions, legalForm, address, isAddressEnabled, datatables,
isStaff);
isStaff, clientCollateralManagements);
}
public static ClientData templateOnTop(final ClientData clientData, final ClientData templateData) {
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName,
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
@@ -281,13 +286,13 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
templateData.clientClassificationOptions, templateData.clientNonPersonConstitutionOptions,
templateData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, templateData.clientLegalFormOptions,
templateData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null,
clientData.isStaff);
clientData.isStaff, clientCollateralManagements);
}
public static ClientData templateWithSavingAccountOptions(final ClientData clientData,
final Collection<SavingsAccountData> savingAccountOptions) {
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName,
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
@@ -299,11 +304,12 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions,
clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, clientData.clientLegalFormOptions,
clientData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null,
clientData.isStaff);
clientData.isStaff, clientCollateralManagements);
}
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups,
final Set<ClientCollateralManagementData> clientCollateralManagements) {
return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName,
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
@@ -314,7 +320,7 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
clientData.clientTypeOptions, clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions,
clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, clientData.clientLegalFormOptions,
clientData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null,
clientData.isStaff);
clientData.isStaff, clientCollateralManagements);
}
@@ -356,13 +362,14 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
final EnumOptionData legalForm = null;
final Boolean isStaff = false;
final ClientNonPersonData clientNonPerson = null;
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate,
imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline,
savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType,
clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions,
clientNonPersonMainBusinessLineOptions, clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null,
null, isStaff);
null, isStaff, clientCollateralManagements);
}
public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
@@ -406,13 +413,14 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
final EnumOptionData legalForm = null;
final Boolean isStaff = false;
final ClientNonPersonData clientNonPerson = null;
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate,
imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline,
savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType,
clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions,
clientNonPersonMainBusinessLineOptions, clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null,
null, isStaff);
null, isStaff, clientCollateralManagements);
}
@@ -443,12 +451,13 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
final List<EnumOptionData> clientLegalFormOptions = null;
final ClientFamilyMembersData familyMemberOptions = null;
final Collection<ClientCollateralManagement> clientCollateralManagements = null;
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate,
imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline,
savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, null, clientType, clientClassification,
clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions,
clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, null, isStaff);
clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, null, isStaff, null);
}
@@ -467,7 +476,8 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions, final ClientNonPersonData clientNonPerson,
final List<EnumOptionData> clientLegalFormOptions, final ClientFamilyMembersData familyMemberOptions,
final EnumOptionData legalForm, final Collection<AddressData> address, final Boolean isAddressEnabled,
final List<DatatableData> datatables, final Boolean isStaff) {
final List<DatatableData> datatables, final Boolean isStaff,
final Set<ClientCollateralManagementData> clientCollateralManagements) {
this.accountNo = accountNo;
this.status = status;
if (status != null) {
@@ -533,7 +543,7 @@ public final class ClientData implements Comparable<ClientData>, Serializable {
this.address = address;
this.isAddressEnabled = isAddressEnabled;
this.datatables = datatables;
this.clientCollateralManagements = clientCollateralManagements;
}
public Long id() {
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -34,6 +35,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
@@ -54,6 +56,7 @@ import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerat
import org.apache.fineract.organisation.office.domain.Office;
import org.apache.fineract.organisation.staff.domain.Staff;
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.useradministration.domain.AppUser;
@@ -234,6 +237,9 @@ public final class Client extends AbstractPersistableCustom {
@Temporal(TemporalType.DATE)
private Date proposedTransferDate;
@OneToMany(mappedBy = "client", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<ClientCollateralManagement> clientCollateralManagements = new HashSet<>();
public static Client createNew(final AppUser currentUser, final Office clientOffice, final Group clientParentGroup, final Staff staff,
final Long savingsProductId, final CodeValue gender, final CodeValue clientType, final CodeValue clientClassification,
final Integer legalForm, final JsonCommand command) {
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.portfolio.client.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
@@ -25,7 +26,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
@@ -53,6 +56,7 @@ import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
import org.apache.fineract.portfolio.address.data.AddressData;
import org.apache.fineract.portfolio.address.service.AddressReadPlatformService;
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import org.apache.fineract.portfolio.client.data.ClientCollateralManagementData;
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
import org.apache.fineract.portfolio.client.data.ClientNonPersonData;
@@ -61,6 +65,8 @@ import org.apache.fineract.portfolio.client.domain.ClientEnumerations;
import org.apache.fineract.portfolio.client.domain.ClientStatus;
import org.apache.fineract.portfolio.client.domain.LegalForm;
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
import org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
@@ -93,6 +99,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
private final ConfigurationReadPlatformService configurationReadPlatformService;
private final EntityDatatableChecksReadService entityDatatableChecksReadService;
private final ColumnValidator columnValidator;
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
@Autowired
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
@@ -102,7 +109,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final AddressReadPlatformService addressReadPlatformService,
final ClientFamilyMembersReadPlatformService clientFamilyMembersReadPlatformService,
final ConfigurationReadPlatformService configurationReadPlatformService,
final EntityDatatableChecksReadService entityDatatableChecksReadService, final ColumnValidator columnValidator) {
final EntityDatatableChecksReadService entityDatatableChecksReadService, final ColumnValidator columnValidator,
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) {
this.context = context;
this.officeReadPlatformService = officeReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource);
@@ -114,6 +122,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
this.configurationReadPlatformService = configurationReadPlatformService;
this.entityDatatableChecksReadService = entityDatatableChecksReadService;
this.columnValidator = columnValidator;
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
}
@Override
@@ -313,12 +322,25 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final ClientData clientData = this.jdbcTemplate.queryForObject(sql, this.clientMapper,
new Object[] { hierarchySearchString, hierarchySearchString, clientId });
// Get client collaterals
final Collection<ClientCollateralManagement> clientCollateralManagements = this.clientCollateralManagementRepositoryWrapper
.getCollateralsPerClient(clientId);
final Set<ClientCollateralManagementData> clientCollateralManagementDataSet = new HashSet<>();
// Map to client collateral data class
for (ClientCollateralManagement clientCollateralManagement : clientCollateralManagements) {
BigDecimal total = clientCollateralManagement.getTotal();
BigDecimal totalCollateral = clientCollateralManagement.getTotalCollateral(total);
clientCollateralManagementDataSet
.add(ClientCollateralManagementData.setCollateralValues(clientCollateralManagement, total, totalCollateral));
}
final String clientGroupsSql = "select " + this.clientGroupsMapper.parentGroupsSchema();
final Collection<GroupGeneralData> parentGroups = this.jdbcTemplate.query(clientGroupsSql, this.clientGroupsMapper,
new Object[] { clientId });
return ClientData.setParentGroups(clientData, parentGroups);
return ClientData.setParentGroups(clientData, parentGroups, clientCollateralManagementDataSet);
} catch (final EmptyResultDataAccessException e) {
throw new ClientNotFoundException(clientId, e);
@@ -100,7 +100,6 @@ public class CollateralsApiResource {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralsApiResourceSwagger.GetLoansLoanIdCollateralsTemplateResponse.class))) })
public String newCollateralTemplate(@Context final UriInfo uriInfo,
@PathParam("loanId") @Parameter(description = "loanId") final Long loanId) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
@@ -85,8 +85,6 @@ final class CollateralsApiResourceSwagger {
private PostLoansLoanIdCollateralsResponse() {}
@Schema(example = "1")
public Integer loanId;
@Schema(example = "12")
public Integer resourceId;
}
@@ -0,0 +1,199 @@
/**
* 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.collateralmanagement.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralTemplateData;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementReadPlatformService;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/clients/{clientId}/collaterals")
@Component
@Scope("singleton")
@Tag(name = "Client Collateral Management", description = "Client Collateral Management is for managing collateral operations")
public class ClientCollateralManagementApiResource {
private final DefaultToApiJsonSerializer<ClientCollateralManagement> apiJsonSerializerService;
private final DefaultToApiJsonSerializer<ClientCollateralManagementData> apiJsonSerializerDataService;
private final DefaultToApiJsonSerializer<LoanCollateralTemplateData> apiJsonSerializerForLoanCollateralTemplateService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final CodeValueReadPlatformService codeValueReadPlatformService;
private final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService;
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList("name", "quantity", "total", "totalCollateral", "clientId", "loanTransactionData"));
public ClientCollateralManagementApiResource(final DefaultToApiJsonSerializer<ClientCollateralManagement> apiJsonSerializerService,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context,
final CodeValueReadPlatformService codeValueReadPlatformService,
final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService,
final DefaultToApiJsonSerializer<ClientCollateralManagementData> apiJsonSerializerDataService,
final DefaultToApiJsonSerializer<LoanCollateralTemplateData> apiJsonSerializerForLoanCollateralTemplateService) {
this.apiJsonSerializerService = apiJsonSerializerService;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.context = context;
this.codeValueReadPlatformService = codeValueReadPlatformService;
this.clientCollateralManagementReadPlatformService = clientCollateralManagementReadPlatformService;
this.apiJsonSerializerDataService = apiJsonSerializerDataService;
this.apiJsonSerializerForLoanCollateralTemplateService = apiJsonSerializerForLoanCollateralTemplateService;
}
@GET
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(summary = "Get Clients Collateral Products", description = "Get Collateral Product of a Client")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.GetClientCollateralManagementsResponse.class)))) })
public String getClientCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId,
@Context final UriInfo uriInfo, @QueryParam("prodId") @Parameter(description = "prodId") final Long prodId) {
this.context.authenticatedUser()
.validateHasReadPermission(CollateralManagementJsonInputParams.CLIENT_COLLATERAL_PRODUCT_READ_PERMISSION.getValue());
List<ClientCollateralManagementData> collateralProductList = null;
collateralProductList = this.clientCollateralManagementReadPlatformService.getClientCollaterals(clientId, prodId);
return this.apiJsonSerializerDataService.serialize(collateralProductList);
}
@GET
@Path("{clientCollateralId}")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(summary = "Get Client Collateral Data", description = "Get Client Collateral Data")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.GetClientCollateralManagementsResponse.class))) })
public String getClientCollateralData(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId,
@PathParam("clientCollateralId") @Parameter(description = "clientCollateralId") final Long collateralId) {
this.context.authenticatedUser()
.validateHasReadPermission(CollateralManagementJsonInputParams.CLIENT_COLLATERAL_PRODUCT_READ_PERMISSION.getValue());
ClientCollateralManagementData clientCollateralManagementData = this.clientCollateralManagementReadPlatformService
.getClientCollateralManagementData(collateralId);
return this.apiJsonSerializerDataService.serialize(clientCollateralManagementData);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Get Client Collateral Template", description = "Get Client Collateral Template")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.GetLoanCollateralManagementTemplate.class)))) })
public String getClientCollateralTemplate(@Context final UriInfo uriInfo,
@PathParam("clientId") @Parameter(description = "clientId") final Long clientId) {
List<LoanCollateralTemplateData> loanCollateralTemplateDataList = this.clientCollateralManagementReadPlatformService
.getLoanCollateralTemplate(clientId);
return this.apiJsonSerializerForLoanCollateralTemplateService.serialize(loanCollateralTemplateDataList);
}
@POST
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(summary = "Add New Collateral For a Client", description = "Add New Collateral For a Client")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PostClientCollateralRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PostClientCollateralResponse.class))) })
public String addCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId,
@Parameter(hidden = true) String apiJsonRequestBody) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().addClientCollateralProduct(clientId).withJson(apiJsonRequestBody)
.build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
@PUT
@Path("{collateralId}")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update New Collateral of a Client", description = "Update New Collateral of a Client")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PutClientCollateralRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PutClientCollateralResponse.class))) })
public String updateCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId,
@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId,
@Parameter(hidden = true) String apiJsonRequestBody) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().updateClientCollateralProduct(clientId, collateralId)
.withJson(apiJsonRequestBody).build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
@DELETE
@Path("{collateralId}")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(summary = "Delete Client Collateral", description = "Delete Client Collateral")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.DeleteClientCollateralResponse.class))) })
public String deleteCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId,
@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().deleteClientCollateralProduct(collateralId, clientId).build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
}
@@ -0,0 +1,155 @@
/**
* 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.collateralmanagement.api;
import io.swagger.v3.oas.annotations.media.Schema;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Set;
final class ClientCollateralManagementApiResourceSwagger {
private ClientCollateralManagementApiResourceSwagger() {}
@Schema(description = "GetClientCollateralManagementsResponse")
public static final class GetClientCollateralManagementsResponse {
private GetClientCollateralManagementsResponse() {}
static final class GetClientCollateralDataResponse {
private GetClientCollateralDataResponse() {}
@Schema(example = "Gold")
public String name;
@Schema(example = "1")
public Long id;
@Schema(example = "10")
public BigDecimal quantity;
@Schema(example = "10000.00")
public BigDecimal total;
@Schema(example = "9000.00")
public BigDecimal totalCollateral;
public GetClientIdResponse client;
public Set<GetTransactionDataResponse> transaction;
}
static final class GetTransactionDataResponse {
private GetTransactionDataResponse() {}
@Schema(example = "5000.00")
public BigDecimal lastRepayment;
@Schema(example = "3000.00")
public BigDecimal remainingAmount;
@Schema(example = "1")
public Long loanId;
@Schema(example = "[2021, 6, 19]")
public LocalDateTime lastRepaymentDate;
}
static final class GetClientIdResponse {
private GetClientIdResponse() {}
@Schema(example = "1")
public Long clientId;
}
}
@Schema(description = "GetLoanCollateralManagementTemplate")
public static final class GetLoanCollateralManagementTemplate {
private GetLoanCollateralManagementTemplate() {}
@Schema(example = "1")
public Long collateralId;
@Schema(example = "10000.00")
public BigDecimal basePrice;
@Schema(example = "40")
public BigDecimal pctToBase;
@Schema(example = "10")
public BigDecimal quantity;
@Schema(example = "Vehicle")
public String name;
}
@Schema(description = "PostClientCollateralRequest")
public static final class PostClientCollateralRequest {
private PostClientCollateralRequest() {}
@Schema(example = "10")
public BigDecimal quantity;
@Schema(example = "1")
public Long collateralId;
@Schema(example = "en")
public String locale;
}
@Schema(description = "PostClientCollateralResponse")
public static final class PostClientCollateralResponse {
private PostClientCollateralResponse() {}
@Schema(example = "14")
public Integer resourceId;
@Schema(example = "1")
public Integer clientId;
}
@Schema(description = "PutClientCollateralRequest")
public static final class PutClientCollateralRequest {
private PutClientCollateralRequest() {}
@Schema(example = "14")
public BigDecimal quantity;
@Schema(example = "en")
public String locale;
}
@Schema(description = "PutClientCollateralResponse")
public static final class PutClientCollateralResponse {
private PutClientCollateralResponse() {}
@Schema(example = "12")
public Integer resourceId;
@Schema(example = "1")
public Integer clientId;
public PutClientCollateralRequest changes;
}
@Schema(description = "DeleteClientCollateralResponse")
public static final class DeleteClientCollateralResponse {
private DeleteClientCollateralResponse() {}
@Schema(example = "12")
public Integer resourceId;
}
}
@@ -0,0 +1,188 @@
/**
* 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.collateralmanagement.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Collection;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
import org.apache.fineract.portfolio.collateralmanagement.data.CollateralManagementData;
import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementReadPlatformService;
import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/collateral-management")
@Component
@Scope("singleton")
@Tag(name = "Collateral Management", description = "Collateral Management is for managing collateral operations")
public class CollateralManagementApiResource {
private final DefaultToApiJsonSerializer<CollateralManagementData> apiJsonSerializerService;
private final DefaultToApiJsonSerializer<CurrencyData> apiJsonSerializerServiceForCurrency;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final CodeValueReadPlatformService codeValueReadPlatformService;
private final CollateralManagementReadPlatformService collateralManagementReadPlatformService;
private final String collateralReadPermission = "COLLATERAL_PRODUCT";
private final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService;
private final CurrencyReadPlatformService currencyReadPlatformService;
@Autowired
public CollateralManagementApiResource(final DefaultToApiJsonSerializer<CollateralManagementData> apiJsonSerializerService,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context,
final CodeValueReadPlatformService codeValueReadPlatformService,
final CollateralManagementReadPlatformService collateralManagementReadPlatformService,
final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService,
final CurrencyReadPlatformService currencyReadPlatformService,
final DefaultToApiJsonSerializer<CurrencyData> apiJsonSerializerServiceForCurrency) {
this.apiJsonSerializerService = apiJsonSerializerService;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.context = context;
this.codeValueReadPlatformService = codeValueReadPlatformService;
this.collateralManagementReadPlatformService = collateralManagementReadPlatformService;
this.clientCollateralManagementReadPlatformService = clientCollateralManagementReadPlatformService;
this.currencyReadPlatformService = currencyReadPlatformService;
this.apiJsonSerializerServiceForCurrency = apiJsonSerializerServiceForCurrency;
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Create a new collateral", description = "Collateral Creation")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PostCollateralManagementProductRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PostCollateralManagementProductResponse.class))) })
public String createCollateral(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().createCollateral().withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
@GET
@Path("{collateralId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Get Collateral", description = "Fetch Collateral")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.class))) })
public String getCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId,
@Context final UriInfo uriInfo) {
this.context.authenticatedUser()
.validateHasReadPermission(CollateralManagementJsonInputParams.COLLATERAL_PRODUCT_READ_PERMISSION.getValue());
final CollateralManagementData collateralManagementData = this.collateralManagementReadPlatformService
.getCollateralProduct(collateralId);
return this.apiJsonSerializerService.serialize(collateralManagementData);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Get All Collaterals", description = "Fetch all Collateral Products")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.class)))) })
public String getAllCollaterals(@Context final UriInfo uriInfo) {
this.context.authenticatedUser()
.validateHasReadPermission(CollateralManagementJsonInputParams.COLLATERAL_PRODUCT_READ_PERMISSION.getValue());
Collection<CollateralManagementData> collateralManagementDataList = this.collateralManagementReadPlatformService
.getAllCollateralProducts();
return this.apiJsonSerializerService.serialize(collateralManagementDataList);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Get Collateral Template", description = "Get Collateral Template")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.GetCollateralProductTemplate.class)))) })
public String getCollateralTemplate(@Context final UriInfo uriInfo) {
Collection<CurrencyData> currencyDataCollection = this.currencyReadPlatformService.retrieveAllPlatformCurrencies();
return this.apiJsonSerializerServiceForCurrency.serialize(currencyDataCollection);
}
@PUT
@Path("{collateralId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update Collateral", description = "Update Collateral")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PutCollateralProductRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PutCollateralProductResponse.class))) })
public String updateCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId,
@Parameter(hidden = true) final String jsonBody) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().updateCollateralProduct(collateralId).withJson(jsonBody).build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
@DELETE
@Path("{collateralId}")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(summary = "Delete a Collateral", description = "Delete Collateral")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.DeleteCollateralProductResponse.class))) })
public String deleteCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCollateralProduct(collateralId).build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
}
@@ -0,0 +1,159 @@
/**
* 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.collateralmanagement.api;
import io.swagger.v3.oas.annotations.media.Schema;
import java.math.BigDecimal;
final class CollateralManagementApiResourceSwagger {
private CollateralManagementApiResourceSwagger() {}
@Schema(description = "GetCollateralManagementsResponse")
public static final class GetCollateralManagementsResponse {
private GetCollateralManagementsResponse() {}
static final class GetCollateralTypeResponse {
private GetCollateralTypeResponse() {}
@Schema(example = "22kt")
public String quality;
}
static final class GetCollateralCurrencyResponse {
private GetCollateralCurrencyResponse() {}
@Schema(example = "USD")
public String code;
}
@Schema(example = "8")
public Long id;
@Schema(example = "Gold")
public String name;
private CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.GetCollateralTypeResponse quality;
@Schema(example = "20000")
public BigDecimal basePrice;
@Schema(example = "gm")
public String unitType;
@Schema(example = "80")
public BigDecimal pctToBase;
public CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.GetCollateralCurrencyResponse currency;
}
@Schema(description = "GetCollateralProductTemplate")
public static final class GetCollateralProductTemplate {
private GetCollateralProductTemplate() {}
static final class GetCurrencyData {
private GetCurrencyData() {}
@Schema(example = "USD")
public String code;
@Schema(example = "Dollars")
public String name;
@Schema(example = "10")
public int decimalPlaces;
@Schema(example = "2")
public Integer inMultiplesOf;
@Schema(example = "USD")
public String displaySymbol;
@Schema(example = "Dollars")
public String nameCode;
@Schema(example = "Dollars")
public String displayLabel;
}
public GetCurrencyData currency;
}
@Schema(description = "PostCollateralManagementProductRequest")
public static final class PostCollateralManagementProductRequest {
private PostCollateralManagementProductRequest() {}
@Schema(example = "22kt")
public String quality;
@Schema(example = "4500")
public BigDecimal basePrice;
@Schema(example = "80")
public BigDecimal pctToBase;
@Schema(example = "gm")
public String unitType;
@Schema(example = "gold")
public String name;
@Schema(example = "USD")
public String currency;
}
@Schema(description = "PostCollateralManagementProductResponse")
public static final class PostCollateralManagementProductResponse {
private PostCollateralManagementProductResponse() {}
@Schema(example = "14")
public Integer resourceId;
}
@Schema(description = "PutCollateralProductRequest")
public static final class PutCollateralProductRequest {
private PutCollateralProductRequest() {}
@Schema(example = "22kt")
public String quality;
@Schema(example = "4500")
public BigDecimal basePrice;
@Schema(example = "80")
public BigDecimal pctToBase;
@Schema(example = "gm")
public String unitType;
@Schema(example = "gold")
public String name;
@Schema(example = "USD")
public String currency;
}
@Schema(description = "PutCollateralProductResponse")
public static final class PutCollateralProductResponse {
private PutCollateralProductResponse() {}
@Schema(example = "12")
public Integer resourceId;
public CollateralManagementApiResourceSwagger.PutCollateralProductRequest changes;
}
@Schema(description = "DeleteCollateralProductResponse")
public static final class DeleteCollateralProductResponse {
private DeleteCollateralProductResponse() {}
@Schema(example = "12")
public Integer resourceId;
}
}
@@ -0,0 +1,42 @@
/**
* 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.collateralmanagement.api;
public enum CollateralManagementJsonInputParams {
NAME("name"), QUALITY("quality"), BASE_PRICE("basePrice"), UNIT_TYPE("unitType"), PCT_TO_BASE("pctToBase"), CURRENCY(
"currency"), COLLATERAL_PRODUCT_READ_PERMISSION("COLLATERAL_PRODUCT"), CLIENT_COLLATERAL_PRODUCT_READ_PERMISSION(
"CLIENT_COLLATERAL_PRODUCT"), QUANTITY("quantity"), TOTAL_COLLATERAL_VALUE("totalCollateralValue");
private final String value;
CollateralManagementJsonInputParams(final String value) {
this.value = value;
}
@Override
public String toString() {
return name().replaceAll("_", " ");
}
public String getValue() {
return this.value;
}
}
@@ -0,0 +1,94 @@
/**
* 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.collateralmanagement.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData;
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/loan-collateral-management")
@Component
@Scope("singleton")
@Tag(name = "Loan Collateral Management", description = "Loan Collateral Management is for managing collateral operations")
public class LoanCollateralManagementApiResources {
private final DefaultToApiJsonSerializer<LoanCollateralResponseData> apiJsonSerializerService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
public LoanCollateralManagementApiResources(final DefaultToApiJsonSerializer<LoanCollateralResponseData> apiJsonSerializerService,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context,
final CodeValueReadPlatformService codeValueReadPlatformService,
final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService) {
this.apiJsonSerializerService = apiJsonSerializerService;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.context = context;
this.codeValueReadPlatformService = codeValueReadPlatformService;
this.loanCollateralManagementReadPlatformService = loanCollateralManagementReadPlatformService;
}
@DELETE
@Path("{id}")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(description = "Delete Loan Collateral", summary = "Delete Loan Collateral")
public String deleteLoanCollateral(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
@PathParam("id") @Parameter(description = "loan collateral id") final Long id) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().deleteLoanCollateral(loanId, id).build();
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
return this.apiJsonSerializerService.serialize(commandProcessingResult);
}
@GET
@Path("{collateralId}")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Operation(description = "Get Loan Collateral Details", summary = "Get Loan Collateral Details")
public String getLoanCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId) {
final LoanCollateralResponseData loanCollateralResponseData = this.loanCollateralManagementReadPlatformService
.getLoanCollateralResponseData(collateralId);
return this.apiJsonSerializerService.serialize(loanCollateralResponseData);
}
}
@@ -0,0 +1,84 @@
/**
* 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.collateralmanagement.data;
import java.math.BigDecimal;
import java.util.List;
public final class ClientCollateralManagementData {
private final String name;
private final BigDecimal quantity;
private final BigDecimal total;
private final BigDecimal totalCollateral;
private final Long clientId;
private final Long id;
private final List<LoanTransactionData> loanTransactionData;
private ClientCollateralManagementData(final String name, final BigDecimal quantity, final BigDecimal total,
final BigDecimal totalCollateral, final Long clientId, final List<LoanTransactionData> loanTransactionData, final Long id) {
this.clientId = clientId;
this.totalCollateral = totalCollateral;
this.total = total;
this.name = name;
this.quantity = quantity;
this.loanTransactionData = loanTransactionData;
this.id = id;
}
public static ClientCollateralManagementData instance(final String name, final BigDecimal quantity, final BigDecimal total,
final BigDecimal totalCollateral, final Long clientId, final List<LoanTransactionData> loanTransactionData, final Long id) {
return new ClientCollateralManagementData(name, quantity, total, totalCollateral, clientId, loanTransactionData, id);
}
public String getName() {
return this.name;
}
public Long getClientId() {
return this.clientId;
}
public BigDecimal getQuantity() {
return this.quantity;
}
public BigDecimal getTotal() {
return this.total;
}
public BigDecimal getTotalCollateral() {
return this.totalCollateral;
}
public Long getId() {
return this.id;
}
public List<LoanTransactionData> getLoanTransactionData() {
return this.loanTransactionData;
}
}
@@ -0,0 +1,58 @@
/**
* 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.collateralmanagement.data;
import java.math.BigDecimal;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
public final class CollateralManagementData {
private String quality;
private BigDecimal basePrice;
private String unitType;
private BigDecimal pctToBase;
private String currency;
private String name;
private Long id;
private CollateralManagementData(final String quality, final BigDecimal basePrice, final String unitType, final BigDecimal pctToBase,
final String currency, final String name, final Long id) {
this.basePrice = basePrice;
this.pctToBase = pctToBase;
this.quality = quality;
this.unitType = unitType;
this.currency = currency;
this.name = name;
this.id = id;
}
public static CollateralManagementData createNew(final CollateralManagementDomain collateralManagementDomain) {
return new CollateralManagementData(collateralManagementDomain.getQuality(), collateralManagementDomain.getBasePrice(),
collateralManagementDomain.getUnitType(), collateralManagementDomain.getPctToBase(),
collateralManagementDomain.getCurrency().getCode(), collateralManagementDomain.getName(),
collateralManagementDomain.getId());
}
}
@@ -0,0 +1,56 @@
/**
* 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.collateralmanagement.data;
import java.math.BigDecimal;
import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
public final class LoanCollateralResponseData {
private Long collateralId;
private BigDecimal quantity;
private BigDecimal total;
private BigDecimal totalCollateral;
private Long clientCollateralId;
private LoanCollateralResponseData(final Long collateralId, final BigDecimal quantity, final BigDecimal total,
final BigDecimal totalCollateral, final Long clientCollateralId) {
this.collateralId = collateralId;
this.quantity = quantity;
this.total = total;
this.totalCollateral = totalCollateral;
this.clientCollateralId = clientCollateralId;
}
public static LoanCollateralResponseData instanceOf(final LoanCollateralManagement loanCollateralManagement, final BigDecimal total,
final BigDecimal totalCollateral) {
return new LoanCollateralResponseData(loanCollateralManagement.getId(), loanCollateralManagement.getQuantity(), total,
totalCollateral, loanCollateralManagement.getClientCollateralManagement().getId());
}
public LoanCollateralManagementData toCommand() {
return new LoanCollateralManagementData(this.clientCollateralId, this.quantity, this.total, this.totalCollateral,
this.collateralId);
}
}
@@ -0,0 +1,51 @@
/**
* 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.collateralmanagement.data;
import java.math.BigDecimal;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
public final class LoanCollateralTemplateData {
private Long collateralId;
private BigDecimal basePrice;
private BigDecimal pctToBase;
private BigDecimal quantity;
private String name;
private LoanCollateralTemplateData(final Long collateralId, final BigDecimal basePrice, final BigDecimal pctToBase,
final BigDecimal quantity, final String name) {
this.quantity = quantity;
this.collateralId = collateralId;
this.basePrice = basePrice;
this.pctToBase = pctToBase;
this.name = name;
}
public static LoanCollateralTemplateData instanceOf(final ClientCollateralManagement clientCollateralManagement) {
return new LoanCollateralTemplateData(clientCollateralManagement.getId(),
clientCollateralManagement.getCollaterals().getBasePrice(), clientCollateralManagement.getCollaterals().getPctToBase(),
clientCollateralManagement.getQuantity(), clientCollateralManagement.getCollaterals().getName());
}
}
@@ -0,0 +1,46 @@
/**
* 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.collateralmanagement.data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
public final class LoanTransactionData {
private final BigDecimal lastRepayment;
private final BigDecimal remainingAmount;
private final Long loanId;
private final LocalDateTime lastRepaymentDate;
private LoanTransactionData(final Long loanId, final LocalDateTime lastRepaymentDate, final BigDecimal remainingAmount,
final BigDecimal lastRepayment) {
this.lastRepayment = lastRepayment;
this.lastRepaymentDate = lastRepaymentDate;
this.remainingAmount = remainingAmount;
this.loanId = loanId;
}
public static LoanTransactionData instance(final Long loanId, final LocalDateTime lastRepaymentDate, final BigDecimal remainingAmount,
final BigDecimal lastRepayment) {
return new LoanTransactionData(loanId, lastRepaymentDate, remainingAmount, lastRepayment);
}
}
@@ -0,0 +1,137 @@
/**
* 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.collateralmanagement.domain;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.collateralmanagement.api.CollateralManagementJsonInputParams;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
@Entity
@Table(name = "m_client_collateral_management")
public class ClientCollateralManagement extends AbstractPersistableCustom {
@Column(name = "quantity", nullable = false, scale = 5, precision = 20)
private BigDecimal quantity;
@ManyToOne(optional = false)
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@ManyToOne(optional = false)
@JoinColumn(name = "collateral_id", nullable = false)
private CollateralManagementDomain collateral;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "clientCollateralManagement", fetch = FetchType.EAGER)
private Set<LoanCollateralManagement> loanCollateralManagementSet = new HashSet<>();
public ClientCollateralManagement() {
}
public ClientCollateralManagement(final BigDecimal quantity, final Client client) {
this.client = client;
this.quantity = quantity;
}
public ClientCollateralManagement(final BigDecimal quantity) {
this.quantity = quantity;
}
private ClientCollateralManagement(final BigDecimal quantity, final Client client,
final CollateralManagementDomain collateralManagementData) {
this.quantity = quantity;
this.client = client;
this.collateral = collateralManagementData;
}
public ClientCollateralManagement createNew(JsonCommand jsonCommand) {
BigDecimal quantity = jsonCommand.bigDecimalValueOfParameterNamed("quantity");
return new ClientCollateralManagement(quantity);
}
public static ClientCollateralManagement createNew(final BigDecimal quantity, final Client client,
final CollateralManagementDomain collateral) {
return new ClientCollateralManagement(quantity, client, collateral);
}
public Map<String, Object> update(JsonCommand command) {
final Map<String, Object> changes = new LinkedHashMap<>(3);
final String quantity = CollateralManagementJsonInputParams.QUANTITY.getValue();
if (command.isChangeInBigDecimalParameterNamed(quantity, this.quantity)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(quantity);
this.quantity = newValue;
changes.put(quantity, this.quantity);
}
return changes;
}
public BigDecimal getTotal() {
if (BigDecimal.ZERO.compareTo(this.quantity) == 0) {
return BigDecimal.ZERO;
}
return this.quantity.multiply(getCollaterals().getBasePrice());
}
public BigDecimal getTotalCollateral(BigDecimal total) {
if (BigDecimal.ZERO.compareTo(total) == 0) {
return BigDecimal.ZERO;
}
return total.multiply(getCollaterals().getPctToBase().divide(BigDecimal.valueOf(100)));
}
public void updateQuantity(BigDecimal quantity) {
this.quantity = quantity;
}
public void updateQuantityAfterLoanClosed(BigDecimal quantity) {
this.quantity = this.quantity.add(quantity);
}
public BigDecimal getQuantity() {
return this.quantity;
}
public Client getClient() {
return this.client;
}
public CollateralManagementDomain getCollaterals() {
return this.collateral;
}
public Set<LoanCollateralManagement> getLoanCollateralManagementSet() {
return this.loanCollateralManagementSet;
}
}
@@ -0,0 +1,33 @@
/**
* 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.collateralmanagement.domain;
import java.util.List;
import org.apache.fineract.portfolio.client.domain.Client;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface ClientCollateralManagementRepository
extends JpaRepository<ClientCollateralManagement, Long>, JpaSpecificationExecutor<ClientCollateralManagement> {
@Query("select clientCollateral from ClientCollateralManagement clientCollateral where clientCollateral.client=:client")
List<ClientCollateralManagement> findByClientId(@Param("client") Client client);
}
@@ -0,0 +1,98 @@
/**
* 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.collateralmanagement.domain;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData;
import org.apache.fineract.portfolio.collateralmanagement.exception.ClientCollateralNotFoundException;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ClientCollateralManagementRepositoryWrapper {
private final ClientCollateralManagementRepository clientCollateralManagementRepository;
private final ClientRepositoryWrapper clientRepositoryWrapper;
private final LoanProductRepository loanProductRepository;
@Autowired
public ClientCollateralManagementRepositoryWrapper(final ClientCollateralManagementRepository clientCollateralManagementRepository,
final ClientRepositoryWrapper clientRepositoryWrapper, final LoanProductRepository loanProductRepository) {
this.clientCollateralManagementRepository = clientCollateralManagementRepository;
this.clientRepositoryWrapper = clientRepositoryWrapper;
this.loanProductRepository = loanProductRepository;
}
public List<ClientCollateralManagement> getCollateralsPerClient(final Long clientId) {
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
return this.clientCollateralManagementRepository.findByClientId(client);
}
public List<ClientCollateralManagementData> getClientCollateralData(final Long clientId, final Long prodId) {
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
String currency = null;
if (prodId != null) {
final LoanProduct loanProduct = this.loanProductRepository.findById(prodId)
.orElseThrow(() -> new LoanProductNotFoundException(prodId));
currency = loanProduct.getCurrency().getCode();
}
List<ClientCollateralManagement> clientCollateralManagements = this.clientCollateralManagementRepository.findByClientId(client);
List<ClientCollateralManagementData> clientCollateralManagementDataSet = new ArrayList<>();
for (ClientCollateralManagement clientCollateralManagement : clientCollateralManagements) {
BigDecimal quantity = clientCollateralManagement.getQuantity();
BigDecimal total = clientCollateralManagement.getTotal();
BigDecimal totalCollateralValue = clientCollateralManagement.getTotalCollateral(total);
if (prodId != null && clientCollateralManagement.getCollaterals().getCurrency().getCode().equals(currency)) {
clientCollateralManagementDataSet
.add(ClientCollateralManagementData.instance(clientCollateralManagement.getCollaterals().getName(), quantity, total,
totalCollateralValue, clientId, null, clientCollateralManagement.getId()));
}
}
return clientCollateralManagementDataSet;
}
public ClientCollateralManagement getCollateral(final Long collateralId) {
return this.clientCollateralManagementRepository.findById(collateralId)
.orElseThrow(() -> new ClientCollateralNotFoundException(collateralId));
}
public ClientCollateralManagement updateClientCollateralProduct(final ClientCollateralManagement clientCollateralManagement) {
return this.clientCollateralManagementRepository.saveAndFlush(clientCollateralManagement);
}
public void deleteClientCollateralProduct(final Long collateralId) {
this.clientCollateralManagementRepository.deleteById(collateralId);
}
public void save(ClientCollateralManagement clientCollateralManagement) {
this.clientCollateralManagementRepository.save(clientCollateralManagement);
}
public void saveAndFlush(ClientCollateralManagement clientCollateralManagement) {
this.clientCollateralManagementRepository.saveAndFlush(clientCollateralManagement);
}
}
@@ -0,0 +1,160 @@
/**
* 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.collateralmanagement.domain;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
import org.apache.fineract.portfolio.collateralmanagement.api.CollateralManagementJsonInputParams;
@Entity
@Table(name = "m_collateral_management")
public class CollateralManagementDomain extends AbstractPersistableCustom {
@Column(name = "name", length = 20, columnDefinition = " ")
private String name;
@Column(name = "quality", nullable = false, length = 40)
private String quality;
@Column(name = "base_price", nullable = false, scale = 5, precision = 20)
private BigDecimal basePrice;
@Column(name = "unit_type", nullable = false, length = 10)
private String unitType;
@Column(name = "pct_to_base", nullable = false, scale = 5, precision = 20)
private BigDecimal pctToBase;
@ManyToOne
@JoinColumn(name = "currency")
private ApplicationCurrency currency;
@OneToMany(mappedBy = "collateral", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
private Set<ClientCollateralManagement> clientCollateralManagements = new HashSet<>();
public CollateralManagementDomain() {
}
private CollateralManagementDomain(final String quality, final BigDecimal basePrice, final String unitType, final BigDecimal pctToBase,
final ApplicationCurrency currency, final String name) {
this.basePrice = basePrice;
this.currency = currency;
this.pctToBase = pctToBase;
this.unitType = unitType;
this.quality = quality;
this.name = name;
}
public static CollateralManagementDomain createNew(JsonCommand jsonCommand, final ApplicationCurrency applicationCurrency) {
String quality = jsonCommand.stringValueOfParameterNamed("quality");
BigDecimal basePrice = jsonCommand.bigDecimalValueOfParameterNamed("basePrice");
BigDecimal pctToBase = jsonCommand.bigDecimalValueOfParameterNamedDefaultToNullIfZero("pctToBase");
String unitType = jsonCommand.stringValueOfParameterNamed("unitType");
String name = jsonCommand.stringValueOfParameterNamed("name");
return new CollateralManagementDomain(quality, basePrice, unitType, pctToBase, applicationCurrency, name);
}
public Map<String, Object> update(final JsonCommand command, final ApplicationCurrency applicationCurrency) {
final Map<String, Object> changes = new LinkedHashMap<>(5);
final String nameParamName = CollateralManagementJsonInputParams.NAME.getValue();
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
final String newValue = command.stringValueOfParameterNamed(nameParamName);
this.name = StringUtils.defaultIfEmpty(newValue, null);
changes.put(nameParamName, this.name);
}
final String qualityParamName = CollateralManagementJsonInputParams.QUALITY.getValue();
if (command.isChangeInStringParameterNamed(qualityParamName, this.quality)) {
final String newValue = command.stringValueOfParameterNamed(qualityParamName);
this.quality = newValue;
changes.put(qualityParamName, this.quality);
}
final String unitTypeParamName = CollateralManagementJsonInputParams.UNIT_TYPE.getValue();
if (command.isChangeInStringParameterNamed(unitTypeParamName, this.unitType)) {
final String newValue = command.stringValueOfParameterNamed(unitTypeParamName);
this.unitType = newValue;
changes.put(unitTypeParamName, this.unitType);
}
this.currency = applicationCurrency;
final String basePriceParamName = CollateralManagementJsonInputParams.BASE_PRICE.getValue();
if (command.isChangeInBigDecimalParameterNamed(basePriceParamName, this.basePrice)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(basePriceParamName);
this.basePrice = newValue;
changes.put(basePriceParamName, this.basePrice);
}
final String pctToBaseParamName = CollateralManagementJsonInputParams.PCT_TO_BASE.getValue();
if (command.isChangeInBigDecimalParameterNamed(pctToBaseParamName, this.pctToBase)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(pctToBaseParamName);
this.pctToBase = newValue;
changes.put(pctToBaseParamName, this.pctToBase);
}
return changes;
}
public String getQuality() {
return this.quality;
}
public String getUnitType() {
return this.unitType;
}
public ApplicationCurrency getCurrency() {
return this.currency;
}
public BigDecimal getBasePrice() {
return this.basePrice;
}
public BigDecimal getPctToBase() {
return this.pctToBase;
}
public String getName() {
return this.name;
}
public Set<ClientCollateralManagement> getClientCollateralManagements() {
return this.clientCollateralManagements;
}
}
@@ -0,0 +1,27 @@
/**
* 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.collateralmanagement.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface CollateralManagementDomainRepository
extends JpaRepository<CollateralManagementDomain, Long>, JpaSpecificationExecutor<CollateralManagementDomain> {
}
@@ -0,0 +1,56 @@
/**
* 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.collateralmanagement.domain;
import java.util.List;
import org.apache.fineract.portfolio.collateral.exception.CollateralNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CollateralManagementRepositoryWrapper {
private final CollateralManagementDomainRepository collateralManagementDomainRepository;
@Autowired
public CollateralManagementRepositoryWrapper(final CollateralManagementDomainRepository collateralManagementDomainRepository) {
this.collateralManagementDomainRepository = collateralManagementDomainRepository;
}
public CollateralManagementDomain create(CollateralManagementDomain collateralData) {
return this.collateralManagementDomainRepository.save(collateralData);
}
public CollateralManagementDomain getCollateral(Long collateralId) {
return this.collateralManagementDomainRepository.findById(collateralId)
.orElseThrow(() -> new CollateralNotFoundException(collateralId));
}
public List<CollateralManagementDomain> getAllCollaterals() {
return this.collateralManagementDomainRepository.findAll();
}
public CollateralManagementDomain update(CollateralManagementDomain collateralManagementData) {
return this.collateralManagementDomainRepository.saveAndFlush(collateralManagementData);
}
public void delete(final Long collateralId) {
this.collateralManagementDomainRepository.deleteById(collateralId);
}
}
@@ -0,0 +1,49 @@
/**
* 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.collateralmanagement.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class ClientCollateralCannotBeDeletedException extends AbstractPlatformDomainRuleException {
/*** enum of reasons of why Collateral cannot be waived **/
public enum ClientCollateralCannotBeDeletedReason {
CLIENT_COLLATERAL_IS_ALREADY_ATTACHED;
public String errorMessage() {
if (name().equalsIgnoreCase("CLIENT_COLLATERAL_IS_ALREADY_ATTACHED")) {
return "This client collateral cannot be deleted as this is associated with one or more loan collaterals";
}
return name();
}
public String errorCode() {
if (name().equalsIgnoreCase("CLIENT_COLLATERAL_IS_ALREADY_ATTACHED")) {
return "error.msg.client.collateral.is.already.associated.with.loan.collateral";
}
return name().toString();
}
}
public ClientCollateralCannotBeDeletedException(final ClientCollateralCannotBeDeletedReason reason, final Long loanCollateralId) {
super(reason.errorCode(), reason.errorMessage(), loanCollateralId);
}
}
@@ -0,0 +1,29 @@
/**
* 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.collateralmanagement.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
public class ClientCollateralNotFoundException extends AbstractPlatformResourceNotFoundException {
public ClientCollateralNotFoundException(final Long id) {
super("error.msg.client.collateral.id.invalid", "Collateral with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,49 @@
/**
* 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.collateralmanagement.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class CollateralCannotBeDeletedException extends AbstractPlatformDomainRuleException {
/*** enum of reasons of why Collateral cannot be waived **/
public enum CollateralCannotBeDeletedReason {
COLLATERAL_IS_ALREADY_ATTACHED;
public String errorMessage() {
if (name().equalsIgnoreCase("COLLATERAL_IS_ALREADY_ATTACHED")) {
return "This collateral cannot be deleted as this is associated with one or more client collaterals";
}
return name();
}
public String errorCode() {
if (name().equalsIgnoreCase("COLLATERAL_IS_ALREADY_ATTACHED")) {
return "error.msg.collateral.is.already.associated.with.client.collateral";
}
return name();
}
}
public CollateralCannotBeDeletedException(final CollateralCannotBeDeletedReason reason, final Long loanCollateralId) {
super(reason.errorCode(), reason.errorMessage(), loanCollateralId);
}
}
@@ -0,0 +1,28 @@
/**
* 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.collateralmanagement.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
public class CollateralNotFoundException extends AbstractPlatformResourceNotFoundException {
public CollateralNotFoundException(final Long id) {
super("error.msg.collateral.id.invalid", "Collateral with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,31 @@
/**
* 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.collateralmanagement.exception;
import java.math.BigDecimal;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class LoanCollateralAmountNotSufficientException extends AbstractPlatformDomainRuleException {
public LoanCollateralAmountNotSufficientException(final BigDecimal amount) {
super("error.msg.loan.disbursement.amount.not.sufficient",
"The disbursement amount `" + amount + "`" + "` is invalid or insufficient to disburse the loan.", new Object[] { amount });
}
}
@@ -0,0 +1,29 @@
/**
* 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.collateralmanagement.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
public class LoanCollateralManagementNotFoundException extends AbstractPlatformResourceNotFoundException {
public LoanCollateralManagementNotFoundException(final Long id) {
super("error.msg.loan.collateral.id.invalid", "Loan Collateral with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,47 @@
/**
* 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.collateralmanagement.handler;
import javax.transaction.Transactional;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "CLIENT_COLLATERAL_PRODUCT", action = "CREATE")
public class AddClientCollateralProductCommandHandler implements NewCommandSourceHandler {
private final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService;
@Autowired
public AddClientCollateralProductCommandHandler(
final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService) {
this.clientCollateralManagementWritePlatformService = clientCollateralManagementWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand jsonCommand) {
return this.clientCollateralManagementWritePlatformService.addClientCollateralProduct(jsonCommand);
}
}
@@ -0,0 +1,46 @@
/**
* 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.collateralmanagement.handler;
import javax.transaction.Transactional;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "COLLATERAL_PRODUCT", action = "CREATE")
public class CreateCollateralProductCommandHandler implements NewCommandSourceHandler {
private final CollateralManagementWritePlatformService collateralManagementWritePlatformService;
@Autowired
public CreateCollateralProductCommandHandler(final CollateralManagementWritePlatformService collateralManagementWritePlatformService) {
this.collateralManagementWritePlatformService = collateralManagementWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand jsonCommand) {
return this.collateralManagementWritePlatformService.createCollateral(jsonCommand);
}
}
@@ -0,0 +1,47 @@
/**
* 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.collateralmanagement.handler;
import javax.transaction.Transactional;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "CLIENT_COLLATERAL_PRODUCT", action = "DELETE")
public class DeleteClientCollateralProductCommandHandler implements NewCommandSourceHandler {
private final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService;
@Autowired
public DeleteClientCollateralProductCommandHandler(
final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService) {
this.clientCollateralManagementWritePlatformService = clientCollateralManagementWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.clientCollateralManagementWritePlatformService.deleteClientCollateralProduct(command.entityId());
}
}
@@ -0,0 +1,46 @@
/**
* 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.collateralmanagement.handler;
import javax.transaction.Transactional;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "COLLATERAL_PRODUCT", action = "DELETE")
public class DeleteCollateralProductHandler implements NewCommandSourceHandler {
private final CollateralManagementWritePlatformService collateralManagementWritePlatformService;
@Autowired
public DeleteCollateralProductHandler(final CollateralManagementWritePlatformService collateralManagementWritePlatformService) {
this.collateralManagementWritePlatformService = collateralManagementWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.collateralManagementWritePlatformService.deleteCollateral(command.entityId());
}
}
@@ -0,0 +1,46 @@
/**
* 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.collateralmanagement.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "LOAN_COLLATERAL_PRODUCT", action = "DELETE")
public class DeleteLoanCollateralManagement implements NewCommandSourceHandler {
private final LoanCollateralManagementWritePlatformService loanCollateralManagementWritePlatformService;
@Autowired
public DeleteLoanCollateralManagement(final LoanCollateralManagementWritePlatformService loanCollateralManagement) {
this.loanCollateralManagementWritePlatformService = loanCollateralManagement;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand jsonCommand) {
return this.loanCollateralManagementWritePlatformService.deleteLoanCollateral(jsonCommand);
}
}
@@ -0,0 +1,47 @@
/**
* 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.collateralmanagement.handler;
import javax.transaction.Transactional;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "CLIENT_COLLATERAL_PRODUCT", action = "UPDATE")
public class UpdateClientCollateralProductCommandHandler implements NewCommandSourceHandler {
private final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService;
@Autowired
public UpdateClientCollateralProductCommandHandler(
final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService) {
this.clientCollateralManagementWritePlatformService = clientCollateralManagementWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand jsonCommand) {
return this.clientCollateralManagementWritePlatformService.updateClientCollateralProduct(jsonCommand);
}
}
@@ -0,0 +1,47 @@
/**
* 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.collateralmanagement.handler;
import javax.transaction.Transactional;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "COLLATERAL_PRODUCT", action = "UPDATE")
public class UpdateCollateralProductCommandHandler implements NewCommandSourceHandler {
private final CollateralManagementWritePlatformService collateralManagementWritePlatformService;
@Autowired
public UpdateCollateralProductCommandHandler(final CollateralManagementWritePlatformService collateralManagementWritePlatformService) {
this.collateralManagementWritePlatformService = collateralManagementWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.collateralManagementWritePlatformService.updateCollateral(command.entityId(), command);
}
}
@@ -0,0 +1,33 @@
/**
* 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.collateralmanagement.serialization;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
public class CollateralManagementCommandFromApiJsonDeserializer {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public CollateralManagementCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
}
@@ -0,0 +1,33 @@
/**
* 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.collateralmanagement.service;
import java.util.List;
import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralTemplateData;
public interface ClientCollateralManagementReadPlatformService {
ClientCollateralManagementData getClientCollateralManagementData(Long collateralId);
List<ClientCollateralManagementData> getClientCollaterals(Long clientId, Long prodId);
List<LoanCollateralTemplateData> getLoanCollateralTemplate(Long clientId);
}
@@ -0,0 +1,104 @@
/**
* 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.collateralmanagement.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralTemplateData;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanTransactionData;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ClientCollateralManagementReadPlatformServiceImpl implements ClientCollateralManagementReadPlatformService {
private final PlatformSecurityContext context;
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
private final LoanTransactionRepository loanTransactionRepository;
@Autowired
public ClientCollateralManagementReadPlatformServiceImpl(final PlatformSecurityContext context,
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper,
final LoanTransactionRepository loanTransactionRepository) {
this.context = context;
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
this.loanTransactionRepository = loanTransactionRepository;
}
@Override
public List<ClientCollateralManagementData> getClientCollaterals(final Long clientId, final Long prodId) {
return this.clientCollateralManagementRepositoryWrapper.getClientCollateralData(clientId, prodId);
}
@Override
public List<LoanCollateralTemplateData> getLoanCollateralTemplate(Long clientId) {
this.context.authenticatedUser();
Collection<ClientCollateralManagement> clientCollateralManagements = this.clientCollateralManagementRepositoryWrapper
.getCollateralsPerClient(clientId);
List<LoanCollateralTemplateData> loanCollateralTemplateDataList = new ArrayList<>();
for (ClientCollateralManagement clientCollateralManagement : clientCollateralManagements) {
loanCollateralTemplateDataList.add(LoanCollateralTemplateData.instanceOf(clientCollateralManagement));
}
return loanCollateralTemplateDataList;
}
@Override
public ClientCollateralManagementData getClientCollateralManagementData(final Long collateralId) {
final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
.getCollateral(collateralId);
BigDecimal basePrice = clientCollateralManagement.getCollaterals().getBasePrice();
BigDecimal pctToBase = clientCollateralManagement.getCollaterals().getPctToBase().divide(BigDecimal.valueOf(100));
BigDecimal total = BigDecimal.ZERO;
BigDecimal totalCollateral = BigDecimal.ZERO;
BigDecimal quantity = clientCollateralManagement.getQuantity();
if (quantity.compareTo(BigDecimal.ZERO) != 0) {
total = basePrice.multiply(quantity);
totalCollateral = total.multiply(pctToBase);
}
Set<LoanCollateralManagement> loanCollateralManagementSet = clientCollateralManagement.getLoanCollateralManagementSet();
List<LoanTransactionData> loanTransactionDataList = new ArrayList<>();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagementSet) {
if (loanCollateralManagement.getLoanTransaction() != null) {
Long transactionId = loanCollateralManagement.getLoanTransaction().getId();
LoanTransaction loanTransaction = this.loanTransactionRepository.findById(transactionId)
.orElseThrow(() -> new LoanTransactionNotFoundException(transactionId));
LoanTransactionData loanTransactionData = LoanTransactionData.instance(loanTransaction.getLoan().getId(),
loanTransaction.getCreatedDateTime(), loanTransaction.getOutstandingLoanBalance(),
loanTransaction.getPrincipalPortion());
loanTransactionDataList.add(loanTransactionData);
}
}
return ClientCollateralManagementData.instance(clientCollateralManagement.getCollaterals().getName(),
clientCollateralManagement.getQuantity(), total, totalCollateral, clientCollateralManagement.getClient().getId(),
loanTransactionDataList, clientCollateralManagement.getId());
}
}
@@ -0,0 +1,32 @@
/**
* 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.collateralmanagement.service;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
public interface ClientCollateralManagementWritePlatformService {
CommandProcessingResult addClientCollateralProduct(JsonCommand command);
CommandProcessingResult updateClientCollateralProduct(JsonCommand command);
CommandProcessingResult deleteClientCollateralProduct(Long collateralId);
}
@@ -0,0 +1,181 @@
/**
* 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.collateralmanagement.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.transaction.Transactional;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.collateralmanagement.exception.ClientCollateralCannotBeDeletedException;
import org.apache.fineract.portfolio.collateralmanagement.exception.ClientCollateralNotFoundException;
import org.apache.fineract.portfolio.collateralmanagement.exception.CollateralNotFoundException;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ClientCollateralManagementWritePlatformServiceImpl implements ClientCollateralManagementWritePlatformService {
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
private final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper;
private final ClientRepositoryWrapper clientRepositoryWrapper;
@Autowired
public ClientCollateralManagementWritePlatformServiceImpl(
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper,
final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper,
final ClientRepositoryWrapper clientRepositoryWrapper) {
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
this.collateralManagementRepositoryWrapper = collateralManagementRepositoryWrapper;
this.clientRepositoryWrapper = clientRepositoryWrapper;
}
@Transactional
@Override
public CommandProcessingResult addClientCollateralProduct(final JsonCommand command) {
validateForCreation(command);
Long collateralId = command.longValueOfParameterNamed("collateralId");
BigDecimal quantity = command.bigDecimalValueOfParameterNamed("quantity");
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(command.getClientId(), false);
final CollateralManagementDomain collateralManagementData = this.collateralManagementRepositoryWrapper.getCollateral(collateralId);
final ClientCollateralManagement clientCollateralManagement = ClientCollateralManagement.createNew(quantity, client,
collateralManagementData);
this.clientCollateralManagementRepositoryWrapper.save(clientCollateralManagement);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withClientId(command.getClientId())
.withEntityId(clientCollateralManagement.getId()).build();
}
private void validateForCreation(final JsonCommand command) {
String errorCode = "parameter.";
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client-collateral");
if (!command.parameterExists("collateralId")) {
errorCode += "collateralId.not.exists";
baseDataValidator.reset().parameter("collateralId").failWithCode(errorCode);
}
if (!command.parameterExists("quantity")) {
errorCode += ".quantity.not.exists";
baseDataValidator.reset().parameter("quantity").failWithCode(errorCode);
} else {
BigDecimal quantity = command.bigDecimalValueOfParameterNamed("quantity");
baseDataValidator.reset().parameter("quantity").value(quantity).notNull().positiveAmount();
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
@Transactional
@Override
public CommandProcessingResult updateClientCollateralProduct(final JsonCommand command) {
validateForUpdate(command);
final ClientCollateralManagement collateral = this.clientCollateralManagementRepositoryWrapper.getCollateral(command.entityId());
final Map<String, Object> changes = collateral.update(command);
this.clientCollateralManagementRepositoryWrapper.updateClientCollateralProduct(collateral);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(command.entityId())
.withClientId(command.getClientId()).with(changes).build();
}
private void validateForUpdate(final JsonCommand command) {
final Long clientCollateralId = command.entityId();
String errorCode = "parameter.";
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client-collateral");
BigDecimal quantity = null;
if (!command.parameterExists("quantity")) {
errorCode += ".quantity.not.exists";
baseDataValidator.reset().parameter("quantity").failWithCode(errorCode);
} else {
quantity = command.bigDecimalValueOfParameterNamed("quantity");
baseDataValidator.reset().parameter("quantity").value(quantity).notNull().positiveAmount();
}
final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
.getCollateral(clientCollateralId);
if (clientCollateralManagement == null) {
throw new ClientCollateralNotFoundException(clientCollateralId);
}
BigDecimal totalQuantity = BigDecimal.ZERO;
if (clientCollateralManagement.getLoanCollateralManagementSet().size() > 0) {
for (LoanCollateralManagement loanCollateralManagement : clientCollateralManagement.getLoanCollateralManagementSet()) {
totalQuantity = totalQuantity.add(loanCollateralManagement.getQuantity());
}
}
if (totalQuantity.compareTo(quantity) >= 0) {
baseDataValidator.reset().parameter("quantity").value(quantity).notLessThanMin(totalQuantity);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
@Transactional
@Override
public CommandProcessingResult deleteClientCollateralProduct(final Long collateralId) {
final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
.getCollateral(collateralId);
validateForDeletion(clientCollateralManagement, collateralId);
this.clientCollateralManagementRepositoryWrapper.deleteClientCollateralProduct(collateralId);
return new CommandProcessingResultBuilder().withEntityId(collateralId).build();
}
private void validateForDeletion(final ClientCollateralManagement clientCollateralManagement, final Long clientCollateralId) {
if (clientCollateralManagement == null) {
throw new CollateralNotFoundException(clientCollateralId);
}
if (clientCollateralManagement.getLoanCollateralManagementSet().size() > 0) {
for (LoanCollateralManagement loanCollateralManagement : clientCollateralManagement.getLoanCollateralManagementSet()) {
if (loanCollateralManagement.getIsReleased() == 0) {
throw new ClientCollateralCannotBeDeletedException(
ClientCollateralCannotBeDeletedException.ClientCollateralCannotBeDeletedReason.CLIENT_COLLATERAL_IS_ALREADY_ATTACHED,
clientCollateralId);
}
}
}
}
}
@@ -0,0 +1,30 @@
/**
* 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.collateralmanagement.service;
import java.util.List;
import org.apache.fineract.portfolio.collateralmanagement.data.CollateralManagementData;
public interface CollateralManagementReadPlatformService {
CollateralManagementData getCollateralProduct(Long collateralId);
List<CollateralManagementData> getAllCollateralProducts();
}
@@ -0,0 +1,61 @@
/**
* 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.collateralmanagement.service;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.collateralmanagement.data.CollateralManagementData;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CollateralManagementReadPlatformServiceImpl implements CollateralManagementReadPlatformService {
private final PlatformSecurityContext context;
private final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper;
@Autowired
public CollateralManagementReadPlatformServiceImpl(final PlatformSecurityContext context,
final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper) {
this.context = context;
this.collateralManagementRepositoryWrapper = collateralManagementRepositoryWrapper;
}
@Override
public CollateralManagementData getCollateralProduct(Long collateralId) {
final CollateralManagementDomain collateralManagementDomain = this.collateralManagementRepositoryWrapper
.getCollateral(collateralId);
return CollateralManagementData.createNew(collateralManagementDomain);
}
@Override
public List<CollateralManagementData> getAllCollateralProducts() {
final List<CollateralManagementDomain> collateralManagementDomainSet = this.collateralManagementRepositoryWrapper
.getAllCollaterals();
List<CollateralManagementData> collateralManagementDataList = new ArrayList<>();
for (CollateralManagementDomain collateralManagementDomain : collateralManagementDomainSet) {
collateralManagementDataList.add(CollateralManagementData.createNew(collateralManagementDomain));
}
return collateralManagementDataList;
}
}
@@ -0,0 +1,31 @@
/**
* 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.collateralmanagement.service;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
public interface CollateralManagementWritePlatformService {
CommandProcessingResult createCollateral(JsonCommand command);
CommandProcessingResult updateCollateral(Long collateralId, JsonCommand command);
CommandProcessingResult deleteCollateral(Long collateralId);
}
@@ -0,0 +1,176 @@
/**
* 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.collateralmanagement.service;
import com.google.gson.JsonElement;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepository;
import org.apache.fineract.portfolio.collateralmanagement.api.CollateralManagementJsonInputParams;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.collateralmanagement.exception.CollateralCannotBeDeletedException;
import org.apache.fineract.portfolio.collateralmanagement.exception.CollateralNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CollateralManagementWritePlatformServiceImpl implements CollateralManagementWritePlatformService {
private final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper;
private final ApplicationCurrencyRepository applicationCurrencyRepository;
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public CollateralManagementWritePlatformServiceImpl(final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper,
final ApplicationCurrencyRepository applicationCurrencyRepository, final FromJsonHelper fromApiJsonHelper) {
this.collateralManagementRepositoryWrapper = collateralManagementRepositoryWrapper;
this.applicationCurrencyRepository = applicationCurrencyRepository;
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Transactional
@Override
public CommandProcessingResult createCollateral(final JsonCommand jsonCommand) {
validateForCreation(jsonCommand);
final String currencyParamName = jsonCommand.stringValueOfParameterNamed(CollateralManagementJsonInputParams.CURRENCY.getValue());
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneByCode(currencyParamName);
final CollateralManagementDomain collateral = CollateralManagementDomain.createNew(jsonCommand, applicationCurrency);
this.collateralManagementRepositoryWrapper.create(collateral);
return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(collateral.getId()).build();
}
private void validateForCreation(JsonCommand jsonCommand) {
final JsonElement jsonElement = this.fromApiJsonHelper.parse(jsonCommand.json());
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collateral-management");
if (!jsonCommand.parameterExists("locale")) {
baseDataValidator.reset().parameter("locale").notNull().failWithCode("locale.not.exists");
} else {
final String locale = this.fromApiJsonHelper.extractStringNamed("locale", jsonElement);
baseDataValidator.reset().parameter("locale").value(locale).notNull();
}
if (!jsonCommand.parameterExists(CollateralManagementJsonInputParams.CURRENCY.getValue())) {
baseDataValidator.reset().parameter(CollateralManagementJsonInputParams.CURRENCY.getValue()).notNull()
.failWithCode("currency.not.exists");
} else {
final String currency = this.fromApiJsonHelper.extractStringNamed("currency", jsonElement);
baseDataValidator.reset().parameter("currency").value(currency).notNull();
}
if (!jsonCommand.parameterExists("quality")) {
baseDataValidator.reset().parameter(CollateralManagementJsonInputParams.QUALITY.getValue()).notNull()
.failWithCode("quality.not.exists");
} else {
final String quality = this.fromApiJsonHelper.extractStringNamed("quality", jsonElement);
baseDataValidator.reset().parameter("quality").value(quality).notNull();
}
if (!jsonCommand.parameterExists("basePrice")) {
baseDataValidator.reset().parameter("basePrice").notNull().notBlank().failWithCode("basePrice.not.exists");
} else {
final BigDecimal basePrice = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("basePrice", jsonElement);
baseDataValidator.reset().parameter("basePrice").value(basePrice).notNull().positiveAmount();
}
if (!jsonCommand.parameterExists("unitType")) {
baseDataValidator.reset().parameter("unitType").notNull().notBlank().failWithCode("unitType.not.exists");
} else {
final String unitType = this.fromApiJsonHelper.extractStringNamed("unitType", jsonElement);
baseDataValidator.reset().parameter("unitType").value(unitType).notNull();
}
if (!jsonCommand.parameterExists("pctToBase")) {
baseDataValidator.reset().parameter("pctToBase").notNull().notBlank().failWithCode("pctToBase.not.exists");
} else {
final BigDecimal basePrice = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("pctToBase", jsonElement);
baseDataValidator.reset().parameter("pctToBase").value(basePrice).notNull().positiveAmount();
}
if (!jsonCommand.parameterExists("name")) {
baseDataValidator.reset().parameter("name").notNull().notBlank().failWithCode("name.not.exists");
} else {
final String unitType = this.fromApiJsonHelper.extractStringNamed("name", jsonElement);
baseDataValidator.reset().parameter("name").value(unitType).notNull();
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
@Transactional
@Override
public CommandProcessingResult updateCollateral(final Long collateralId, JsonCommand jsonCommand) {
final CollateralManagementDomain collateral = this.collateralManagementRepositoryWrapper.getCollateral(collateralId);
final String currencyParamName = CollateralManagementJsonInputParams.CURRENCY.getValue();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository
.findOneByCode(jsonCommand.stringValueOfParameterNamed(currencyParamName));
if (jsonCommand.isChangeInStringParameterNamed(currencyParamName, applicationCurrency.getCode())) {
final String newValue = jsonCommand.stringValueOfParameterNamed(currencyParamName);
applicationCurrency.setCode(newValue);
}
final Map<String, Object> changes = collateral.update(jsonCommand, applicationCurrency);
this.collateralManagementRepositoryWrapper.update(collateral);
return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(jsonCommand.entityId())
.with(changes).build();
}
@Transactional
@Override
public CommandProcessingResult deleteCollateral(final Long collateralId) {
final CollateralManagementDomain collateralManagementDomain = this.collateralManagementRepositoryWrapper
.getCollateral(collateralId);
validateForDeletion(collateralManagementDomain, collateralId);
this.collateralManagementRepositoryWrapper.delete(collateralId);
return new CommandProcessingResultBuilder().withEntityId(collateralId).build();
}
private void validateForDeletion(final CollateralManagementDomain collateralManagementDomain, final Long collateralId) {
if (collateralManagementDomain == null) {
throw new CollateralNotFoundException(collateralId);
}
if (collateralManagementDomain.getClientCollateralManagements().size() > 0) {
for (ClientCollateralManagement clientCollateralManagement : collateralManagementDomain.getClientCollateralManagements()) {
if (clientCollateralManagement.getQuantity().compareTo(BigDecimal.ZERO) > 0) {
throw new CollateralCannotBeDeletedException(
CollateralCannotBeDeletedException.CollateralCannotBeDeletedReason.COLLATERAL_IS_ALREADY_ATTACHED,
collateralId);
}
}
}
}
}
@@ -0,0 +1,106 @@
/**
* 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.collateralmanagement.service;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.collateralmanagement.exception.LoanCollateralManagementNotFoundException;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository;
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LoanCollateralAssembler {
private final FromJsonHelper fromApiJsonHelper;
private final CodeValueRepositoryWrapper codeValueRepository;
private final LoanCollateralManagementRepository loanCollateralRepository;
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
@Autowired
public LoanCollateralAssembler(final FromJsonHelper fromApiJsonHelper, final CodeValueRepositoryWrapper codeValueRepository,
final LoanCollateralManagementRepository loanCollateralRepository,
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.codeValueRepository = codeValueRepository;
this.loanCollateralRepository = loanCollateralRepository;
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
}
public Set<LoanCollateralManagement> fromParsedJson(final JsonElement element) {
final Set<LoanCollateralManagement> collateralItems = new HashSet<>();
JsonObject jsonObject = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(jsonObject);
if (jsonObject.has("collateral") && jsonObject.get("collateral").isJsonArray()) {
JsonArray collaterals = jsonObject.get("collateral").getAsJsonArray();
for (int i = 0; i < collaterals.size(); i++) {
final JsonObject collateralItemElement = collaterals.get(i).getAsJsonObject();
final Long id = this.fromApiJsonHelper.extractLongNamed("id", collateralItemElement);
final Long collateralId = this.fromApiJsonHelper.extractLongNamed("clientCollateralId", collateralItemElement);
final ClientCollateralManagement clientCollateral = this.clientCollateralManagementRepositoryWrapper
.getCollateral(collateralId);
final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed("quantity", collateralItemElement, locale);
BigDecimal updatedClientQuantity = null;
if (id == null) {
updatedClientQuantity = clientCollateral.getQuantity().subtract(quantity);
if (BigDecimal.ZERO.compareTo(updatedClientQuantity) > 0) {
throw new InvalidAmountOfCollateralQuantity(quantity);
}
clientCollateral.updateQuantity(updatedClientQuantity);
collateralItems.add(LoanCollateralManagement.from(clientCollateral, quantity));
} else {
LoanCollateralManagement loanCollateralManagement = this.loanCollateralRepository.findById(id)
.orElseThrow(() -> new LoanCollateralManagementNotFoundException(id));
if (loanCollateralManagement.getQuantity().compareTo(quantity) != 0) {
updatedClientQuantity = clientCollateral.getQuantity().add(loanCollateralManagement.getQuantity())
.subtract(quantity);
if (BigDecimal.ZERO.compareTo(updatedClientQuantity) > 0) {
throw new InvalidAmountOfCollateralQuantity(quantity);
}
} else {
updatedClientQuantity = quantity;
}
clientCollateral.updateQuantity(updatedClientQuantity);
collateralItems
.add(LoanCollateralManagement.fromExisting(clientCollateral, quantity, loanCollateralManagement.getLoanData(),
loanCollateralManagement.getLoanTransaction(), loanCollateralManagement.getId()));
}
}
}
return collateralItems;
}
}
@@ -0,0 +1,32 @@
/**
* 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.collateralmanagement.service;
import java.util.List;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
public interface LoanCollateralManagementReadPlatformService {
List<LoanCollateralManagement> getLoanCollaterals(Long loanId);
LoanCollateralResponseData getLoanCollateralResponseData(Long collateralId);
List<LoanCollateralResponseData> getLoanCollateralResponseDataList(Long loanId);
}
@@ -0,0 +1,90 @@
/**
* 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.collateralmanagement.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
import org.apache.fineract.portfolio.collateralmanagement.exception.LoanCollateralManagementNotFoundException;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LoanCollateralManagementReadPlatformServiceImpl implements LoanCollateralManagementReadPlatformService {
private final PlatformSecurityContext context;
private LoanCollateralManagementRepository loanCollateralManagementRepository;
private LoanRepository loanRepository;
@Autowired
public LoanCollateralManagementReadPlatformServiceImpl(final PlatformSecurityContext context,
final LoanCollateralManagementRepository loanCollateralManagementRepository, final LoanRepository loanRepository) {
this.context = context;
this.loanCollateralManagementRepository = loanCollateralManagementRepository;
this.loanRepository = loanRepository;
}
@Override
public List<LoanCollateralManagement> getLoanCollaterals(Long loanId) {
this.context.authenticatedUser();
Loan loan = this.loanRepository.findById(loanId).orElseThrow(() -> new LoanNotFoundException(loanId));
return this.loanCollateralManagementRepository.findByLoan(loan);
}
@Override
public LoanCollateralResponseData getLoanCollateralResponseData(Long collateralId) {
this.context.authenticatedUser();
LoanCollateralManagement loanCollateralManagement = this.loanCollateralManagementRepository.findById(collateralId)
.orElseThrow(() -> new LoanCollateralManagementNotFoundException(collateralId));
final CollateralManagementDomain collateralManagementDomain = loanCollateralManagement.getClientCollateralManagement()
.getCollaterals();
BigDecimal quantity = loanCollateralManagement.getQuantity();
BigDecimal total = quantity.multiply(collateralManagementDomain.getBasePrice());
BigDecimal totalCollateral = total.multiply(collateralManagementDomain.getPctToBase()).divide(BigDecimal.valueOf(100));
return LoanCollateralResponseData.instanceOf(loanCollateralManagement, total, totalCollateral);
}
@Override
public List<LoanCollateralResponseData> getLoanCollateralResponseDataList(Long loanId) {
this.context.authenticatedUser();
Loan loan = this.loanRepository.findById(loanId).orElseThrow(() -> new LoanNotFoundException(loanId));
List<LoanCollateralResponseData> loanCollateralResponseDataCollection = new ArrayList<>();
Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
final CollateralManagementDomain collateralManagementDomain = loanCollateralManagement.getClientCollateralManagement()
.getCollaterals();
BigDecimal quantity = loanCollateralManagement.getQuantity();
BigDecimal total = quantity.multiply(collateralManagementDomain.getBasePrice());
BigDecimal totalCollateral = total.multiply(collateralManagementDomain.getPctToBase()).divide(BigDecimal.valueOf(100));
loanCollateralResponseDataCollection
.add(LoanCollateralResponseData.instanceOf(loanCollateralManagement, total, totalCollateral));
}
return loanCollateralResponseDataCollection;
}
}
@@ -0,0 +1,27 @@
/**
* 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.collateralmanagement.service;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
public interface LoanCollateralManagementWritePlatformService {
CommandProcessingResult deleteLoanCollateral(JsonCommand command);
}
@@ -0,0 +1,60 @@
/**
* 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.collateralmanagement.service;
import java.math.BigDecimal;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class LoanCollateralManagementWritePlatformServiceImpl implements LoanCollateralManagementWritePlatformService {
private final LoanCollateralManagementRepository loanCollateralManagementRepository;
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
@Autowired
public LoanCollateralManagementWritePlatformServiceImpl(final LoanCollateralManagementRepository loanCollateralManagementRepository,
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) {
this.loanCollateralManagementRepository = loanCollateralManagementRepository;
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
}
@Transactional
@Override
public CommandProcessingResult deleteLoanCollateral(JsonCommand command) {
final Long id = command.entityId();
final LoanCollateralManagement loanCollateralManagement = this.loanCollateralManagementRepository.findById(id).orElseThrow();
ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement();
BigDecimal loanQuantity = loanCollateralManagement.getQuantity();
BigDecimal clientQuantity = clientCollateralManagement.getQuantity();
clientCollateralManagement.updateQuantity(clientQuantity.add(loanQuantity));
this.clientCollateralManagementRepositoryWrapper.saveAndFlush(clientCollateralManagement);
this.loanCollateralManagementRepository.deleteById(id);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(id).withLoanId(command.getLoanId())
.build();
}
}
@@ -99,6 +99,7 @@ public interface LoanApiConstants {
String APPROVED_AMOUNT_IS_LESS_THAN_SUM_OF_TRANCHES = "sum.of.multi.disburse.amounts.must.be.equal.to.or.lesser.than.approved.principal";
String DISBURSEMENT_DATES_NOT_IN_ORDER = "disbursements.should.be.ordered.based.on.their.disbursement.dates";
String DISBURSEMENT_DATE_BEFORE_ERROR = "disbursement.date.of.tranche.cannot.be.before.expected.disbursement.date";
String LOAN_COLLATERAL_TOTAL_VALUE_SHOULD_BE_SUFFICIENT = "sum.of.multi.collateral.values.must.equal.or.greater.than.principal.amount";
String isFloatingInterestRate = "isFloatingInterestRate";
String interestRateDifferential = "interestRateDifferential";
@@ -98,6 +98,8 @@ import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.collateral.data.CollateralData;
import org.apache.fineract.portfolio.collateral.service.CollateralReadPlatformService;
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData;
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService;
import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
import org.apache.fineract.portfolio.fund.data.FundData;
import org.apache.fineract.portfolio.fund.service.FundReadPlatformService;
@@ -108,6 +110,7 @@ import org.apache.fineract.portfolio.loanaccount.data.GlimRepaymentTemplate;
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData;
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData;
@@ -253,6 +256,7 @@ public class LoansApiResource {
private final ConfigurationDomainService configurationDomainService;
private final DefaultToApiJsonSerializer<GlimRepaymentTemplate> glimTemplateToApiJsonSerializer;
private final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService;
private final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService;
@Autowired
public LoansApiResource(final PlatformSecurityContext context, final LoanReadPlatformService loanReadPlatformService,
@@ -278,7 +282,8 @@ public class LoansApiResource {
final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService, final RateReadService rateReadService,
final ConfigurationDomainService configurationDomainService,
final DefaultToApiJsonSerializer<GlimRepaymentTemplate> glimTemplateToApiJsonSerializer,
final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService) {
final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService,
final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService) {
this.context = context;
this.loanReadPlatformService = loanReadPlatformService;
this.loanProductReadPlatformService = loanProductReadPlatformService;
@@ -310,6 +315,7 @@ public class LoansApiResource {
this.configurationDomainService = configurationDomainService;
this.glimTemplateToApiJsonSerializer = glimTemplateToApiJsonSerializer;
this.glimAccountInfoReadPlatformService = glimAccountInfoReadPlatformService;
this.loanCollateralManagementReadPlatformService = loanCollateralManagementReadPlatformService;
}
/*
@@ -535,6 +541,8 @@ public class LoansApiResource {
PortfolioAccountData linkedAccount = null;
Collection<DisbursementData> disbursementData = null;
Collection<LoanTermVariationsData> emiAmountVariations = null;
Collection<LoanCollateralResponseData> loanCollateralManagements = null;
Collection<LoanCollateralManagementData> loanCollateralManagementData = new ArrayList<>();
final Set<String> mandatoryResponseParameters = new HashSet<>();
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
@@ -604,9 +612,12 @@ public class LoansApiResource {
if (associationParameters.contains("collateral")) {
mandatoryResponseParameters.add("collateral");
collateral = this.loanCollateralReadPlatformService.retrieveCollaterals(loanId);
if (CollectionUtils.isEmpty(collateral)) {
collateral = null;
loanCollateralManagements = this.loanCollateralManagementReadPlatformService.getLoanCollateralResponseDataList(loanId);
for (LoanCollateralResponseData loanCollateralManagement : loanCollateralManagements) {
loanCollateralManagementData.add(loanCollateralManagement.toCommand());
}
if (CollectionUtils.isEmpty(loanCollateralManagements)) {
loanCollateralManagements = null;
}
}
@@ -725,12 +736,12 @@ public class LoansApiResource {
}
final LoanAccountData loanAccount = LoanAccountData.associationsAndTemplate(loanBasicDetails, repaymentSchedule, loanRepayments,
charges, collateral, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions,
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions, loanCollateralOptions, calendarOptions,
notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations, overdueCharges, paidInAdvanceTemplate,
interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled);
charges, loanCollateralManagementData, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions,
repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions,
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions,
loanCollateralOptions, calendarOptions, notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations,
overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
mandatoryResponseParameters);
@@ -37,7 +37,6 @@ import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
import org.apache.fineract.portfolio.calendar.data.CalendarData;
import org.apache.fineract.portfolio.charge.data.ChargeData;
import org.apache.fineract.portfolio.collateral.data.CollateralData;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
import org.apache.fineract.portfolio.fund.data.FundData;
@@ -135,7 +134,7 @@ public final class LoanAccountData {
private final LoanScheduleData repaymentSchedule;
private final Collection<LoanTransactionData> transactions;
private final Collection<LoanChargeData> charges;
private final Collection<CollateralData> collateral;
private final Collection<LoanCollateralManagementData> collateral;
private final Collection<GuarantorData> guarantors;
private final CalendarData meeting;
private final Collection<NoteData> notes;
@@ -245,14 +244,14 @@ public final class LoanAccountData {
BigDecimal inArrearsTolerance, Long transactionProcessingStrategyId, Integer graceOnPrincipalPayment,
Integer graceOnInterestPayment, Integer graceOnInterestCharged, LocalDate interestChargedFromDate,
LocalDate repaymentsStartingFromDate, Integer rowIndex, String externalId, Long groupId, Collection<LoanChargeData> charges,
String linkAccountId, String locale, String dateFormat) {
String linkAccountId, String locale, String dateFormat, List<LoanCollateralManagementData> loanCollateralManagementData) {
return new LoanAccountData(loanTypeEnumOption, clientId, productId, loanOfficerId, submittedOnDate, fundId, principal,
numberOfRepayments, repaymentEvery, repaidEveryFrequencyEnums, loanTermFrequency, loanTermFrequencyTypeEnum,
nominalInterestRate, expectedDisbursementDate, amortizationEnumOption, interestMethodEnum,
interestCalculationPeriodTypeEnum, inArrearsTolerance, transactionProcessingStrategyId, graceOnPrincipalPayment,
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, repaymentsStartingFromDate, rowIndex, externalId,
null, charges, linkAccountId, locale, dateFormat);
null, charges, linkAccountId, locale, dateFormat, loanCollateralManagementData);
}
public static LoanAccountData importInstanceGroup(EnumOptionData loanTypeEnumOption, Long groupIdforGroupLoan, Long productId,
@@ -268,7 +267,8 @@ public final class LoanAccountData {
numberOfRepayments, repaidEvery, repaidEveryFrequencyEnums, loanTermFrequency, loanTermFrequencyTypeEnum,
nominalInterestRate, null, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance,
transactionProcessingStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
interestChargedFromDate, repaymentsStartingFromDate, rowIndex, externalId, null, null, linkAccountId, locale, dateFormat);
interestChargedFromDate, repaymentsStartingFromDate, rowIndex, externalId, null, null, linkAccountId, locale, dateFormat,
null);
}
private LoanAccountData(EnumOptionData loanType, Long clientId, Long productId, Long loanOfficerId, LocalDate submittedOnDate,
@@ -278,7 +278,8 @@ public final class LoanAccountData {
EnumOptionData interestCalculationPeriodType, BigDecimal inArrearsTolerance, Long transactionProcessingStrategyId,
Integer graceOnPrincipalPayment, Integer graceOnInterestPayment, Integer graceOnInterestCharged,
LocalDate interestChargedFromDate, LocalDate repaymentsStartingFromDate, Integer rowIndex, String externalId, Long groupId,
Collection<LoanChargeData> charges, String linkAccountId, String locale, String dateFormat) {
Collection<LoanChargeData> charges, String linkAccountId, String locale, String dateFormat,
Collection<LoanCollateralManagementData> loanCollateralManagementData) {
this.dateFormat = dateFormat;
this.locale = locale;
this.rowIndex = rowIndex;
@@ -362,7 +363,7 @@ public final class LoanAccountData {
this.repaymentSchedule = null;
this.transactions = null;
this.collateral = null;
this.collateral = loanCollateralManagementData;
this.guarantors = null;
this.meeting = null;
this.notes = null;
@@ -524,7 +525,7 @@ public final class LoanAccountData {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
final Collection<LoanChargeData> charges = null;
final Collection<CollateralData> collateral = null;
final Collection<LoanCollateralManagementData> collateral = null;
final Collection<GuarantorData> guarantors = null;
final Collection<NoteData> notes = null;
final CalendarData calendarData = null;
@@ -665,7 +666,7 @@ public final class LoanAccountData {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
final Collection<LoanChargeData> charges = null;
final Collection<CollateralData> collateral = null;
final Collection<LoanCollateralManagementData> collateral = null;
final Collection<GuarantorData> guarantors = null;
final Collection<NoteData> notes = null;
final CalendarData calendarData = null;
@@ -839,7 +840,7 @@ public final class LoanAccountData {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
final Collection<LoanChargeData> charges = null;
final Collection<CollateralData> collateral = null;
final Collection<LoanCollateralManagementData> collateral = null;
final Collection<GuarantorData> guarantors = null;
final Collection<NoteData> notes = null;
final CalendarData calendarData = null;
@@ -1006,7 +1007,7 @@ public final class LoanAccountData {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
final Collection<CollateralData> collateral = null;
final Collection<LoanCollateralManagementData> collateral = null;
final Collection<GuarantorData> guarantors = null;
final Collection<NoteData> notes = null;
final CalendarData calendarData = null;
@@ -1112,7 +1113,7 @@ public final class LoanAccountData {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
final Collection<CollateralData> collateral = null;
final Collection<LoanCollateralManagementData> collateral = null;
final Collection<GuarantorData> guarantors = null;
final Collection<NoteData> notes = null;
final CalendarData calendarData = null;
@@ -1203,7 +1204,7 @@ public final class LoanAccountData {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
final Collection<LoanChargeData> charges = null;
final Collection<CollateralData> collateral = null;
final Collection<LoanCollateralManagementData> collateral = null;
final Collection<GuarantorData> guarantors = null;
final Collection<NoteData> notes = null;
final CalendarData calendarData = null;
@@ -1265,9 +1266,9 @@ public final class LoanAccountData {
*/
public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final LoanScheduleData repaymentSchedule,
final Collection<LoanTransactionData> transactions, final Collection<LoanChargeData> charges,
final Collection<CollateralData> collateral, final Collection<GuarantorData> guarantors, final CalendarData calendarData,
final Collection<LoanProductData> productOptions, final Collection<EnumOptionData> termFrequencyTypeOptions,
final Collection<EnumOptionData> repaymentFrequencyTypeOptions,
final Collection<LoanCollateralManagementData> collateral, final Collection<GuarantorData> guarantors,
final CalendarData calendarData, final Collection<LoanProductData> productOptions,
final Collection<EnumOptionData> termFrequencyTypeOptions, final Collection<EnumOptionData> repaymentFrequencyTypeOptions,
final Collection<EnumOptionData> repaymentFrequencyNthDayTypeOptions,
final Collection<EnumOptionData> repaymentFrequencyDayOfWeekTypeOptions,
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions,
@@ -1535,7 +1536,7 @@ public final class LoanAccountData {
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate,
final LoanApplicationTimelineData timeline, final LoanSummaryData summary, final BigDecimal feeChargesDueAtDisbursementCharged,
final LoanScheduleData repaymentSchedule, final Collection<LoanTransactionData> transactions,
final Collection<LoanChargeData> charges, final Collection<CollateralData> collateral,
final Collection<LoanChargeData> charges, final Collection<LoanCollateralManagementData> collateral,
final Collection<GuarantorData> guarantors, final CalendarData meeting, final Collection<LoanProductData> productOptions,
final Collection<EnumOptionData> termFrequencyTypeOptions, final Collection<EnumOptionData> repaymentFrequencyTypeOptions,
final Collection<EnumOptionData> repaymentFrequencyNthDayTypeOptions,
@@ -0,0 +1,60 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanaccount.data;
import java.math.BigDecimal;
public class LoanCollateralManagementData {
private final Long clientCollateralId;
private final BigDecimal quantity;
private final BigDecimal total;
private final BigDecimal totalCollateral;
private final Long id;
public LoanCollateralManagementData(final Long clientCollateralIdId, final BigDecimal quantity, final BigDecimal total,
final BigDecimal totalCollateral, final Long id) {
this.clientCollateralId = clientCollateralIdId;
this.quantity = quantity;
this.totalCollateral = totalCollateral;
this.total = total;
this.id = id;
}
public Long getClientCollateralId() {
return this.clientCollateralId;
}
public BigDecimal getQuantity() {
return this.quantity;
}
public BigDecimal getTotal() {
return this.total;
}
public BigDecimal getTotalCollateral() {
return this.totalCollateral;
}
}
@@ -94,7 +94,6 @@ import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeAddedException;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.collateral.data.CollateralData;
import org.apache.fineract.portfolio.collateral.domain.LoanCollateral;
import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
import org.apache.fineract.portfolio.common.domain.NthDayType;
@@ -107,6 +106,7 @@ import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanaccount.command.LoanChargeCommand;
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -312,6 +312,9 @@ public class Loan extends AbstractPersistableCustom {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.LAZY)
private Set<LoanCollateral> collateral = null;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.EAGER)
private Set<LoanCollateralManagement> loanCollateralManagements = new HashSet<>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.LAZY)
private Set<LoanOfficerAssignmentHistory> loanOfficerHistory;
@@ -406,9 +409,10 @@ public class Loan extends AbstractPersistableCustom {
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
final Set<LoanCollateral> collateral, final BigDecimal fixedEmiAmount, final List<LoanDisbursementDetails> disbursementDetails,
final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement,
final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List<Rate> rates) {
final Set<LoanCollateralManagement> collateral, final BigDecimal fixedEmiAmount,
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates) {
final LoanStatus status = null;
final Group group = null;
final Boolean syncDisbursementWithMeeting = null;
@@ -422,7 +426,7 @@ public class Loan extends AbstractPersistableCustom {
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
final Set<LoanCollateral> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates) {
@@ -438,7 +442,7 @@ public class Loan extends AbstractPersistableCustom {
final Integer loanType, final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
final Set<LoanCollateral> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates) {
@@ -456,7 +460,7 @@ public class Loan extends AbstractPersistableCustom {
private Loan(final String accountNo, final Client client, final Group group, final Integer loanType, final Fund fund,
final Staff loanOfficer, final CodeValue loanPurpose, final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProduct loanProduct, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanStatus loanStatus,
final Set<LoanCharge> loanCharges, final Set<LoanCollateral> collateral, final Boolean syncDisbursementWithMeeting,
final Set<LoanCharge> loanCharges, final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting,
final BigDecimal fixedEmiAmount, final List<LoanDisbursementDetails> disbursementDetails,
final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement,
final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List<Rate> rates) {
@@ -494,10 +498,11 @@ public class Loan extends AbstractPersistableCustom {
this.charges = null;
this.summary = new LoanSummary();
}
if (collateral != null && !collateral.isEmpty()) {
this.collateral = associateWithThisLoan(collateral);
if (loanType.equals(1) && collateral != null && !collateral.isEmpty()) {
this.loanCollateralManagements = associateWithThisLoan(collateral);
} else {
this.collateral = null;
this.loanCollateralManagements = null;
}
this.loanOfficerHistory = null;
@@ -557,9 +562,9 @@ public class Loan extends AbstractPersistableCustom {
return loanCharges;
}
private Set<LoanCollateral> associateWithThisLoan(final Set<LoanCollateral> collateral) {
for (final LoanCollateral item : collateral) {
item.associateWith(this);
private Set<LoanCollateralManagement> associateWithThisLoan(final Set<LoanCollateralManagement> collateral) {
for (final LoanCollateralManagement item : collateral) {
item.setLoan(this);
}
return collateral;
}
@@ -1179,12 +1184,12 @@ public class Loan extends AbstractPersistableCustom {
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
}
public void updateLoanCollateral(final Set<LoanCollateral> loanCollateral) {
if (this.collateral == null) {
this.collateral = new HashSet<>();
public void updateLoanCollateral(final Set<LoanCollateralManagement> loanCollateral) {
if (this.loanCollateralManagements == null) {
this.loanCollateralManagements = new HashSet<>();
}
this.collateral.clear();
this.collateral.addAll(associateWithThisLoan(loanCollateral));
this.loanCollateralManagements.clear();
this.loanCollateralManagements.addAll(associateWithThisLoan(loanCollateral));
}
public void updateLoanRates(final List<Rate> loanRates) {
@@ -1333,8 +1338,8 @@ public class Loan extends AbstractPersistableCustom {
}
public Map<String, Object> loanApplicationModification(final JsonCommand command, final Set<LoanCharge> possiblyModifedLoanCharges,
final Set<LoanCollateral> possiblyModifedLoanCollateralItems, final AprCalculator aprCalculator, boolean isChargesModified,
final LoanProduct loanProduct) {
final Set<LoanCollateralManagement> possiblyModifedLoanCollateralItems, final AprCalculator aprCalculator,
boolean isChargesModified, final LoanProduct loanProduct) {
final Map<String, Object> actualChanges = this.loanRepaymentScheduleDetail.updateLoanApplicationAttributes(command, aprCalculator);
final MonetaryCurrency currency = new MonetaryCurrency(loanProduct.getCurrency().getCode(),
@@ -1546,10 +1551,16 @@ public class Loan extends AbstractPersistableCustom {
}
final String collateralParamName = "collateral";
if (command.parameterExists(collateralParamName)) {
if (!possiblyModifedLoanCollateralItems.equals(this.collateral)) {
actualChanges.put(collateralParamName, listOfLoanCollateralData(possiblyModifedLoanCollateralItems));
if (command.parameterExists(collateralParamName) && possiblyModifedLoanCollateralItems != null) {
if (possiblyModifedLoanCollateralItems.size() != 0) {
Set<LoanCollateralManagement> loanCollateralManagements = this.loanCollateralManagements;
boolean isTrue = possiblyModifedLoanCollateralItems.equals(loanCollateralManagements);
if (!isTrue) {
actualChanges.put(collateralParamName, getLoanCollateralDataFormCommand(possiblyModifedLoanCollateralItems));
}
}
}
@@ -1921,19 +1932,18 @@ public class Loan extends AbstractPersistableCustom {
return list;
}
private CollateralData[] listOfLoanCollateralData(final Set<LoanCollateral> setOfLoanCollateral) {
private LoanCollateralManagementData[] getLoanCollateralDataFormCommand(final Set<LoanCollateralManagement> setOfLoanCollateral) {
CollateralData[] existingLoanCollateral = null;
LoanCollateralManagementData[] existingLoanCollateral = null;
final List<CollateralData> loanCollateralList = new ArrayList<>();
for (final LoanCollateral loanCollateral : setOfLoanCollateral) {
final List<LoanCollateralManagementData> loanCollateralList = new ArrayList<>();
for (final LoanCollateralManagement loanCollateral : setOfLoanCollateral) {
final CollateralData data = loanCollateral.toData();
loanCollateralList.add(loanCollateral.toCommand());
loanCollateralList.add(data);
}
existingLoanCollateral = loanCollateralList.toArray(new CollateralData[loanCollateralList.size()]);
existingLoanCollateral = loanCollateralList.toArray(new LoanCollateralManagementData[loanCollateralList.size()]);
return existingLoanCollateral;
}
@@ -3013,6 +3023,7 @@ public class Loan extends AbstractPersistableCustom {
final String errorMessage = "Transfer funds is allowed only for loan accounts with overpaid status ";
throw new InvalidLoanStateTransitionException("transaction", "is.not.a.overpaid.loan", errorMessage);
}
loanTransaction.updateLoan(this);
if (loanTransaction.isNotZero(loanCurrency())) {
@@ -6597,6 +6608,7 @@ public class Loan extends AbstractPersistableCustom {
checkAndFetchLazyCollection(this.loanTermVariations);
checkAndFetchLazyCollection(this.collateral);
checkAndFetchLazyCollection(this.loanOfficerHistory);
checkAndFetchLazyCollection(this.loanCollateralManagements);
}
private void checkAndFetchLazyCollection(Collection lazyCollection) {
@@ -6641,4 +6653,8 @@ public class Loan extends AbstractPersistableCustom {
this.loanType = loanType;
}
public Set<LoanCollateralManagement> getLoanCollateralManagements() {
return this.loanCollateralManagements;
}
}
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Map;
import java.util.Set;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
@@ -48,6 +49,10 @@ public interface LoanAccountDomainService {
LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate,
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId);
void updateLoanCollateralTransaction(Set<LoanCollateralManagement> loanCollateralManagementList);
void updateLoanCollateralStatus(Set<LoanCollateralManagement> loanCollateralManagementSet, Integer isReleased);
/**
* This method is to recalculate and accrue the income till the last accrued date. this method is used when the
* schedule changes due to interest recalculation
@@ -101,6 +101,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
private final BusinessEventNotifierService businessEventNotifierService;
private final LoanUtilService loanUtilService;
private final StandingInstructionRepository standingInstructionRepository;
private final LoanCollateralManagementRepository loanCollateralManagementRepository;
@Autowired
public LoanAccountDomainServiceJpa(final LoanAssembler loanAccountAssembler, final LoanRepositoryWrapper loanRepositoryWrapper,
@@ -114,7 +115,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
final LoanAccrualPlatformService loanAccrualPlatformService, final PlatformSecurityContext context,
final BusinessEventNotifierService businessEventNotifierService, final LoanUtilService loanUtilService,
final StandingInstructionRepository standingInstructionRepository) {
final StandingInstructionRepository standingInstructionRepository,
final LoanCollateralManagementRepository loanCollateralManagementRepository) {
this.loanAccountAssembler = loanAccountAssembler;
this.loanRepositoryWrapper = loanRepositoryWrapper;
this.loanTransactionRepository = loanTransactionRepository;
@@ -132,6 +134,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.businessEventNotifierService = businessEventNotifierService;
this.loanUtilService = loanUtilService;
this.standingInstructionRepository = standingInstructionRepository;
this.loanCollateralManagementRepository = loanCollateralManagementRepository;
}
@Transactional
@@ -144,6 +147,21 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
isRecoveryRepayment, isAccountTransfer, holidayDetailDto, isHolidayValidationDone, false);
}
@Transactional
@Override
public void updateLoanCollateralTransaction(Set<LoanCollateralManagement> loanCollateralManagementSet) {
this.loanCollateralManagementRepository.saveAll(loanCollateralManagementSet);
}
@Transactional
@Override
public void updateLoanCollateralStatus(Set<LoanCollateralManagement> loanCollateralManagementSet, Integer isReleased) {
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagementSet) {
loanCollateralManagement.setIsReleased(isReleased);
}
this.loanCollateralManagementRepository.saveAll(loanCollateralManagementSet);
}
@Transactional
@Override
public LoanTransaction makeRepayment(final Loan loan, final CommandProcessingResultBuilder builderResult,
@@ -232,7 +250,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) {
try {
this.loanTransactionRepository.save(newRepaymentTransaction);
LoanTransaction loanTransaction = this.loanTransactionRepository.save(newRepaymentTransaction);
} catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
@@ -524,6 +543,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
throw new GeneralPlatformDomainRuleException(globalisationMessageCode, e.getMessage(), e);
}
}
}
private void generateLoanScheduleAccrualData(final LocalDate accruedTill,
@@ -0,0 +1,124 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanaccount.domain;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
@Entity
@Table(name = "m_loan_collateral_management")
public class LoanCollateralManagement extends AbstractPersistableCustom {
@Column(name = "quantity", nullable = false, scale = 5, precision = 20)
private BigDecimal quantity;
@ManyToOne()
@JoinColumn(name = "transaction_id")
private LoanTransaction loanTransaction = null;
@ManyToOne(optional = false)
@JoinColumn(name = "loan_id", referencedColumnName = "id", nullable = false)
private Loan loan;
@Column(name = "is_released", nullable = false, columnDefinition = "0")
private Integer isReleased = Integer.valueOf(0);
@ManyToOne(optional = false)
@JoinColumn(name = "client_collateral_id", nullable = false)
private ClientCollateralManagement clientCollateralManagement;
public LoanCollateralManagement() {
}
public LoanCollateralManagement(final BigDecimal quantity, final Integer isReleased) {
this.quantity = quantity;
this.isReleased = isReleased;
}
private LoanCollateralManagement(final BigDecimal quantity, final ClientCollateralManagement clientCollateralManagement) {
this.clientCollateralManagement = clientCollateralManagement;
this.quantity = quantity;
}
public void setLoan(Loan loan) {
this.loan = loan;
}
public static LoanCollateralManagement from(final ClientCollateralManagement clientCollateralManagement, final BigDecimal quantity) {
return new LoanCollateralManagement(quantity, clientCollateralManagement);
}
public static LoanCollateralManagement fromExisting(final ClientCollateralManagement clientCollateralManagement,
final BigDecimal quantity, final Loan loan, final LoanTransaction transaction, final Long id) {
LoanCollateralManagement loanCollateralManagementInstance = new LoanCollateralManagement(quantity, clientCollateralManagement);
loanCollateralManagementInstance.setLoan(loan);
loanCollateralManagementInstance.setLoanTransactionData(transaction);
loanCollateralManagementInstance.setId(id);
return loanCollateralManagementInstance;
}
public void setClientCollateralManagement(final ClientCollateralManagement clientCollateralManagement) {
this.clientCollateralManagement = clientCollateralManagement;
}
public void setLoanTransactionData(final LoanTransaction loanTransaction) {
this.loanTransaction = loanTransaction;
}
public void setIsReleased(final Integer isReleased) {
this.isReleased = isReleased;
}
public void setQuantity(final BigDecimal quantity) {
this.quantity = quantity;
}
public BigDecimal getQuantity() {
return this.quantity;
}
public Loan getLoanData() {
return this.loan;
}
public LoanTransaction getLoanTransaction() {
return this.loanTransaction;
}
public ClientCollateralManagement getClientCollateralManagement() {
return this.clientCollateralManagement;
}
public Integer getIsReleased() {
return this.isReleased;
}
public LoanCollateralManagementData toCommand() {
return new LoanCollateralManagementData(this.clientCollateralManagement.getId(), this.getQuantity(), null, null, getId());
}
}
@@ -0,0 +1,32 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanaccount.domain;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
public interface LoanCollateralManagementRepository
extends JpaRepository<LoanCollateralManagement, Long>, JpaSpecificationExecutor<LoanCollateralManagement> {
@Query("select loanCollaterals from LoanCollateralManagement loanCollaterals where loanCollaterals.loan=:loan")
List<LoanCollateralManagement> findByLoan(Loan loan);
}
@@ -129,6 +129,9 @@ public class LoanTransaction extends AbstractPersistableCustom {
@Column(name = "manually_adjusted_or_reversed", nullable = false)
private boolean manuallyAdjustedOrReversed;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "loanTransaction")
private Set<LoanCollateralManagement> loanCollateralManagementSet = new HashSet<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JoinColumn(name = "loan_transaction_id", referencedColumnName = "id", nullable = false)
private Set<LoanTransactionToRepaymentScheduleMapping> loanTransactionToRepaymentScheduleMappings = new HashSet<>();
@@ -823,6 +826,10 @@ public class LoanTransaction extends AbstractPersistableCustom {
|| this.isNonMonetaryTransaction() || this.isIncomePosting());
}
public Set<LoanCollateralManagement> getLoanCollateralManagementSet() {
return this.loanCollateralManagementSet;
}
// TODO missing hashCode(), equals(Object obj), but probably OK as long as
// this is never stored in a Collection.
}
@@ -0,0 +1,36 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanaccount.exception;
import java.math.BigDecimal;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class InvalidAmountOfCollateralQuantity extends AbstractPlatformDomainRuleException {
public InvalidAmountOfCollateralQuantity(final BigDecimal quantity) {
super("error.msg.loan.collateral.failed",
"The collateral quantity value`" + quantity.toString() + "`" + "` cannot exceed the available quantity",
new Object[] { quantity.toString() });
}
public InvalidAmountOfCollateralQuantity(final String defaultUserMessage, final String entity, final Object... defaultUserMessageArgs) {
super("error.msg.loan." + entity, defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -0,0 +1,35 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanaccount.exception;
import java.math.BigDecimal;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class InvalidAmountOfCollaterals extends AbstractPlatformDomainRuleException {
public InvalidAmountOfCollaterals(final BigDecimal amount) {
super("error.msg.loan.collateral.failed",
"The total collateral value`" + amount.toString() + "`" + "` should be greater than or equal to the loan amount",
new Object[] { amount.toString() });
}
public InvalidAmountOfCollaterals(final String defaultUserMessage, final String entity, final Object... defaultUserMessageArgs) {
super("error.msg.loan." + entity, defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -41,9 +41,13 @@ import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterExc
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity;
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals;
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
@@ -88,16 +92,20 @@ public final class LoanApplicationCommandFromApiJsonHelper {
LoanApiConstants.createStandingInstructionAtDisbursementParameterName, LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose,
LoanApiConstants.datatables, LoanApiConstants.isEqualAmortizationParam, LoanProductConstants.RATES_PARAM_NAME,
LoanApiConstants.applicationId, // glim specific
LoanApiConstants.lastApplication, LoanApiConstants.daysInYearTypeParameterName)); // glim specific
LoanApiConstants.lastApplication, LoanApiConstants.daysInYearTypeParameterName)); // glim
// specific
private final FromJsonHelper fromApiJsonHelper;
private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper;
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
@Autowired
public LoanApplicationCommandFromApiJsonHelper(final FromJsonHelper fromApiJsonHelper,
final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper) {
final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper,
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.apiJsonHelper = apiJsonHelper;
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
}
public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans, final LoanProduct loanProduct) {
@@ -414,38 +422,54 @@ public final class LoanApplicationCommandFromApiJsonHelper {
}
}
// collateral
final String collateralParameterName = "collateral";
if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
if (topLevelJsonElement.get("collateral").isJsonArray()) {
/**
* TODO: Add collaterals for other loan accounts if needed. For now it's only applicable for individual
* accounts. (loanType.isJLG() || loanType.isGLIM())
*/
final Type collateralParameterTypeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id", "type", "value", "description"));
final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray();
for (int i = 1; i <= array.size(); i++) {
final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject();
if (!StringUtils.isBlank(loanTypeStr)) {
final AccountType loanType = AccountType.fromName(loanTypeStr);
final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement);
this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson, supportedParameters);
if (loanType.isIndividualAccount()) {
// collateral
final String collateralParameterName = "collateral";
if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
if (topLevelJsonElement.get("collateral").isJsonArray()) {
final Long collateralTypeId = this.fromApiJsonHelper.extractLongNamed("type", collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("type", i).value(collateralTypeId).notNull()
.integerGreaterThanZero();
final Type collateralParameterTypeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("clientCollateralId", "quantity"));
final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray();
for (int i = 1; i <= array.size(); i++) {
final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject();
final BigDecimal collateralValue = this.fromApiJsonHelper.extractBigDecimalNamed("value", collateralItemElement,
locale);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("value", i).value(collateralValue)
.ignoreIfNull().positiveAmount();
final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement);
this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson,
supportedParameters);
final String description = this.fromApiJsonHelper.extractStringNamed("description", collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("description", i).value(description).notBlank()
.notExceedingLengthOf(500);
final Long clientCollateralId = this.fromApiJsonHelper.extractLongNamed("clientCollateralId",
collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("clientCollateralId", i)
.value(clientCollateralId).notNull().integerGreaterThanZero();
final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed("quantity", collateralItemElement,
locale);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("quantity", i).value(quantity).notNull()
.positiveAmount();
final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
.getCollateral(clientCollateralId);
if (clientCollateralId != null
&& BigDecimal.valueOf(0).compareTo(clientCollateralManagement.getQuantity()) >= 0) {
throw new InvalidAmountOfCollateralQuantity(clientCollateralManagement.getQuantity());
}
}
} else {
baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot();
}
}
} else {
baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot();
}
}
@@ -847,38 +871,67 @@ public final class LoanApplicationCommandFromApiJsonHelper {
}
}
// collateral
final String collateralParameterName = "collateral";
if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
if (topLevelJsonElement.get("collateral").isJsonArray()) {
final String loanTypeParameterName = "loanType";
final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(loanTypeParameterName, element);
baseDataValidator.reset().parameter(loanTypeParameterName).value(loanTypeStr).notNull();
final Type collateralParameterTypeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id", "type", "value", "description"));
final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray();
for (int i = 1; i <= array.size(); i++) {
final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject();
if (!StringUtils.isBlank(loanTypeStr)) {
final AccountType loanType = AccountType.fromName(loanTypeStr);
final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement);
this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson, supportedParameters);
if (loanType.isInvalid()) {
baseDataValidator.reset().parameter(loanTypeParameterName).value(loanType.getValue()).isOneOfEnumValues(AccountType.class);
}
final Long collateralTypeId = this.fromApiJsonHelper.extractLongNamed("type", collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("type", i).value(collateralTypeId).notNull()
.integerGreaterThanZero();
if (!loanType.isInvalid() && loanType.isIndividualAccount()) {
// collateral
final String collateralParameterName = "collateral";
if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
if (topLevelJsonElement.get("collateral").isJsonArray()) {
final BigDecimal collateralValue = this.fromApiJsonHelper.extractBigDecimalNamed("value", collateralItemElement,
locale);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("value", i).value(collateralValue)
.ignoreIfNull().positiveAmount();
final Type collateralParameterTypeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id", "clientCollateralId", "quantity"));
final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray();
BigDecimal totalAmount = BigDecimal.ZERO;
for (int i = 1; i <= array.size(); i++) {
final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject();
final String description = this.fromApiJsonHelper.extractStringNamed("description", collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("description", i).value(description).notBlank()
.notExceedingLengthOf(500);
final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement);
this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson,
supportedParameters);
final Long id = this.fromApiJsonHelper.extractLongNamed("id", collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("id", i).value(id).ignoreIfNull();
final Long clientCollateralId = this.fromApiJsonHelper.extractLongNamed("clientCollateralId",
collateralItemElement);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("clientCollateralId", i)
.value(clientCollateralId).notNull().integerGreaterThanZero();
final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed("quantity", collateralItemElement,
locale);
baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("quantity", i).value(quantity).notNull()
.positiveAmount();
if (clientCollateralId != null || quantity != null) {
BigDecimal baseAmount = this.clientCollateralManagementRepositoryWrapper.getCollateral(clientCollateralId)
.getCollaterals().getBasePrice();
BigDecimal pctToBase = this.clientCollateralManagementRepositoryWrapper.getCollateral(clientCollateralId)
.getCollaterals().getPctToBase();
BigDecimal total = baseAmount.multiply(pctToBase).multiply(quantity);
totalAmount = totalAmount.add(total);
}
}
if (principal != null) {
if (principal.compareTo(totalAmount) > 0 || array.size() == 0) {
throw new InvalidAmountOfCollaterals(totalAmount);
}
}
} else {
baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot();
}
}
} else {
baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot();
}
}
@@ -1201,6 +1254,20 @@ public final class LoanApplicationCommandFromApiJsonHelper {
}
}
public void validateLoanForCollaterals(final Loan loan, final BigDecimal total) {
String errorCode = "";
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
if (loan.getProposedPrincipal().compareTo(total) >= 0) {
errorCode = LoanApiConstants.LOAN_COLLATERAL_TOTAL_VALUE_SHOULD_BE_SUFFICIENT;
baseDataValidator.reset().parameter("collaterals").failWithCode(errorCode);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
private void validatePartialPeriodSupport(final Integer interestCalculationPeriodType, final DataValidatorBuilder baseDataValidator,
final JsonElement element, final LoanProduct loanProduct) {
if (interestCalculationPeriodType != null) {
@@ -81,8 +81,9 @@ import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
import org.apache.fineract.portfolio.collateral.domain.LoanCollateral;
import org.apache.fineract.portfolio.collateral.service.CollateralAssembler;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepository;
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler;
import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BusinessEntity;
import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BusinessEvents;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
@@ -100,6 +101,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepositor
import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
@@ -165,7 +168,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private final ClientRepositoryWrapper clientRepository;
private final LoanProductRepository loanProductRepository;
private final LoanChargeAssembler loanChargeAssembler;
private final CollateralAssembler loanCollateralAssembler;
private final LoanCollateralAssembler loanCollateralAssembler;
private final AprCalculator aprCalculator;
private final AccountNumberGenerator accountNumberGenerator;
private final LoanSummaryWrapper loanSummaryWrapper;
@@ -194,6 +197,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private final GLIMAccountInfoRepository glimRepository;
private final LoanRepository loanRepository;
private final GSIMReadPlatformService gsimReadPlatformService;
private final LoanCollateralManagementRepository loanCollateralManagementRepository;
private final ClientCollateralManagementRepository clientCollateralManagementRepository;
@Autowired
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
@@ -201,7 +206,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer,
final LoanProductDataValidator loanProductCommandFromApiJsonDeserializer, final AprCalculator aprCalculator,
final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler,
final CollateralAssembler loanCollateralAssembler, final LoanRepositoryWrapper loanRepositoryWrapper,
final LoanCollateralAssembler loanCollateralAssembler, final LoanRepositoryWrapper loanRepositoryWrapper,
final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService,
final ClientRepositoryWrapper clientRepository, final LoanProductRepository loanProductRepository,
final AccountNumberGenerator accountNumberGenerator, final LoanSummaryWrapper loanSummaryWrapper,
@@ -220,7 +225,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService,
final GLIMAccountInfoWritePlatformService glimAccountInfoWritePlatformService, final GLIMAccountInfoRepository glimRepository,
final LoanRepository loanRepository, final GSIMReadPlatformService gsimReadPlatformService, final RateAssembler rateAssembler,
final LoanProductReadPlatformService loanProductReadPlatformService) {
final LoanProductReadPlatformService loanProductReadPlatformService,
final LoanCollateralManagementRepository loanCollateralManagementRepository,
final ClientCollateralManagementRepository clientCollateralManagementRepository) {
this.context = context;
this.fromJsonHelper = fromJsonHelper;
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
@@ -261,6 +268,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.glimRepository = glimRepository;
this.loanRepository = loanRepository;
this.gsimReadPlatformService = gsimReadPlatformService;
this.loanCollateralManagementRepository = loanCollateralManagementRepository;
this.clientCollateralManagementRepository = clientCollateralManagementRepository;
}
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -813,8 +822,16 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
}
}
final Set<LoanCollateral> possiblyModifedLoanCollateralItems = this.loanCollateralAssembler
.fromParsedJson(command.parsedJson());
Set<LoanCollateralManagement> possiblyModifedLoanCollateralItems = null;
if (command.parameterExists("loanType")) {
final String loanTypeStr = command.stringValueOfParameterNamed("loanType");
final AccountType loanType = AccountType.fromName(loanTypeStr);
if (!StringUtils.isBlank(loanTypeStr) && loanType.isIndividualAccount()) {
possiblyModifedLoanCollateralItems = this.loanCollateralAssembler.fromParsedJson(command.parsedJson());
}
}
final Map<String, Object> changes = existingLoanApplication.loanApplicationModification(command, possiblyModifedLoanCharges,
possiblyModifedLoanCollateralItems, this.aprCalculator, isChargeModified, loanProductForValidations);
@@ -991,10 +1008,19 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
existingLoanApplication.updateTransactionProcessingStrategy(strategy);
}
final String collateralParamName = "collateral";
if (changes.containsKey(collateralParamName)) {
final Set<LoanCollateral> loanCollateral = this.loanCollateralAssembler.fromParsedJson(command.parsedJson());
existingLoanApplication.updateLoanCollateral(loanCollateral);
/**
* TODO: Allow other loan types if needed.
*/
if (command.parameterExists("loanType")) {
final String loanTypeStr = command.stringValueOfParameterNamed("loanType");
final AccountType loanType = AccountType.fromName(loanTypeStr);
if (!StringUtils.isBlank(loanTypeStr) && loanType.isIndividualAccount()) {
final String collateralParamName = "collateral";
if (changes.containsKey(collateralParamName)) {
existingLoanApplication.updateLoanCollateral(possiblyModifedLoanCollateralItems);
}
}
}
final String chargesParamName = "charges";
@@ -1268,6 +1294,15 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.accountAssociationsRepository.delete(accountAssociations);
}
Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
BigDecimal quantity = loanCollateralManagement.getQuantity();
ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement();
clientCollateralManagement.updateQuantityAfterLoanClosed(quantity);
loanCollateralManagement.setIsReleased(Integer.valueOf(1));
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
}
this.loanRepositoryWrapper.delete(loanId);
return new CommandProcessingResultBuilder() //
@@ -1610,6 +1645,20 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final Map<String, Object> changes = loan.loanApplicationWithdrawnByApplicant(currentUser, command,
defaultLoanLifecycleStateMachine());
// Release attached collaterals
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement();
clientCollateralManagement
.updateQuantity(clientCollateralManagement.getQuantity().add(loanCollateralManagement.getQuantity()));
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
loanCollateralManagement.setIsReleased(Integer.valueOf(1));
}
loan.updateLoanCollateral(loanCollateralManagements);
}
if (!changes.isEmpty()) {
this.loanRepositoryWrapper.save(loan);
@@ -24,9 +24,11 @@ import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
@@ -43,12 +45,13 @@ import org.apache.fineract.organisation.staff.exception.StaffNotFoundException;
import org.apache.fineract.organisation.staff.exception.StaffRoleException;
import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
import org.apache.fineract.portfolio.accountdetails.service.AccountEnumerations;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
import org.apache.fineract.portfolio.collateral.domain.LoanCollateral;
import org.apache.fineract.portfolio.collateral.service.CollateralAssembler;
import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain;
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler;
import org.apache.fineract.portfolio.fund.domain.Fund;
import org.apache.fineract.portfolio.fund.domain.FundRepository;
import org.apache.fineract.portfolio.fund.exception.FundNotFoundException;
@@ -61,6 +64,7 @@ import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
@@ -69,6 +73,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository;
import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals;
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
@@ -101,7 +106,7 @@ public class LoanAssembler {
private final CodeValueRepositoryWrapper codeValueRepository;
private final LoanScheduleAssembler loanScheduleAssembler;
private final LoanChargeAssembler loanChargeAssembler;
private final CollateralAssembler loanCollateralAssembler;
private final LoanCollateralAssembler collateralAssembler;
private final LoanSummaryWrapper loanSummaryWrapper;
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
private final HolidayRepository holidayRepository;
@@ -117,7 +122,7 @@ public class LoanAssembler {
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
final StaffRepository staffRepository, final CodeValueRepositoryWrapper codeValueRepository,
final LoanScheduleAssembler loanScheduleAssembler, final LoanChargeAssembler loanChargeAssembler,
final CollateralAssembler loanCollateralAssembler, final LoanSummaryWrapper loanSummaryWrapper,
final LoanCollateralAssembler collateralAssembler, final LoanSummaryWrapper loanSummaryWrapper,
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService,
final WorkingDaysRepositoryWrapper workingDaysRepository, final LoanUtilService loanUtilService, RateAssembler rateAssembler) {
@@ -132,7 +137,7 @@ public class LoanAssembler {
this.codeValueRepository = codeValueRepository;
this.loanScheduleAssembler = loanScheduleAssembler;
this.loanChargeAssembler = loanChargeAssembler;
this.loanCollateralAssembler = loanCollateralAssembler;
this.collateralAssembler = collateralAssembler;
this.loanSummaryWrapper = loanSummaryWrapper;
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
this.holidayRepository = holidayRepository;
@@ -178,7 +183,8 @@ public class LoanAssembler {
final LoanProduct loanProduct = this.loanProductRepository.findById(productId)
.orElseThrow(() -> new LoanProductNotFoundException(productId));
final BigDecimal amount = this.fromApiJsonHelper
.extractBigDecimalWithLocaleNamed(LoanApiConstants.disbursementPrincipalParameterName, element);
final Fund fund = findFundByIdIfProvided(fundId);
final Staff loanOfficer = findLoanOfficerByIdIfProvided(loanOfficerId);
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(
@@ -209,7 +215,37 @@ public class LoanAssembler {
loanProduct.maxTrancheCount(), disbursementDetails.size());
}
}
final Set<LoanCollateral> collateral = this.loanCollateralAssembler.fromParsedJson(element);
final String loanTypeParameterName = "loanType";
final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(loanTypeParameterName, element);
final EnumOptionData loanType = AccountEnumerations.loanType(loanTypeStr);
Set<LoanCollateralManagement> collateral = new HashSet<>();
if (!StringUtils.isBlank(loanTypeStr)) {
final AccountType loanAccountType = AccountType.fromName(loanTypeStr);
if (loanAccountType.isIndividualAccount()) {
collateral = this.collateralAssembler.fromParsedJson(element);
if (collateral.size() == 0) {
throw new InvalidAmountOfCollaterals(BigDecimal.ZERO);
}
BigDecimal totalValue = BigDecimal.ZERO;
for (LoanCollateralManagement collateralManagement : collateral) {
final CollateralManagementDomain collateralManagementDomain = collateralManagement.getClientCollateralManagement()
.getCollaterals();
BigDecimal totalCollateral = collateralManagement.getQuantity().multiply(collateralManagementDomain.getBasePrice())
.multiply(collateralManagementDomain.getPctToBase()).divide(BigDecimal.valueOf(100));
totalValue = totalValue.add(totalCollateral);
}
if (amount.compareTo(totalValue) > 0) {
throw new InvalidAmountOfCollaterals(totalValue);
}
}
}
final Set<LoanCharge> loanCharges = this.loanChargeAssembler.fromParsedJson(element, disbursementDetails);
for (final LoanCharge loanCharge : loanCharges) {
if (!loanProduct.hasCurrencyCodeOf(loanCharge.currencyCode())) {
@@ -239,10 +275,6 @@ public class LoanAssembler {
final Boolean isFloatingInterestRate = this.fromApiJsonHelper
.extractBooleanNamed(LoanApiConstants.isFloatingInterestRateParameterName, element);
final String loanTypeParameterName = "loanType";
final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(loanTypeParameterName, element);
final EnumOptionData loanType = AccountEnumerations.loanType(loanTypeStr);
if (clientId != null) {
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
if (client.isNotActive()) {
@@ -264,14 +296,13 @@ public class LoanAssembler {
}
loanApplication = Loan.newIndividualLoanApplicationFromGroup(accountNo, client, group, loanType.getId().intValue(), loanProduct,
fund, loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral,
fund, loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, null,
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates);
} else if (group != null) {
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanType.getId().intValue(), loanProduct, fund, loanOfficer,
loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral,
loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, null,
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates);
@@ -114,6 +114,8 @@ import org.apache.fineract.portfolio.charge.exception.LoanChargeWaiveCannotBeRev
import org.apache.fineract.portfolio.charge.exception.LoanChargeWaiveCannotBeReversedException.LoanChargeWaiveCannotUndoReason;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import org.apache.fineract.portfolio.collateralmanagement.exception.LoanCollateralAmountNotSufficientException;
import org.apache.fineract.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand;
import org.apache.fineract.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
import org.apache.fineract.portfolio.collectionsheet.command.SingleDisbursalCommand;
@@ -141,6 +143,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidByRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge;
@@ -357,6 +360,28 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final Loan loan = this.loanAssembler.assembleFrom(loanId);
// Get disbursedAmount
final BigDecimal disbursedAmount = loan.getDisbursedAmount();
// Get relevant loan collateral modules
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
final Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
BigDecimal totalCollateral = BigDecimal.valueOf(0);
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
BigDecimal quantity = loanCollateralManagement.getQuantity();
BigDecimal pctToBase = loanCollateralManagement.getClientCollateralManagement().getCollaterals().getPctToBase();
BigDecimal basePrice = loanCollateralManagement.getClientCollateralManagement().getCollaterals().getBasePrice();
totalCollateral = totalCollateral.add(quantity.multiply(basePrice).multiply(pctToBase).divide(BigDecimal.valueOf(100)));
}
// Validate the loan collateral value against the disbursedAmount
if (disbursedAmount.compareTo(totalCollateral) > 0) {
throw new LoanCollateralAmountNotSufficientException(disbursedAmount);
}
}
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
// validate ActualDisbursement Date Against Expected Disbursement Date
@@ -901,8 +926,26 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final HolidayDetailDTO holidayDetailDto = null;
boolean isAccountTransfer = false;
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, transactionDate, transactionAmount, paymentDetail,
noteText, txnExternalId, isRecoveryRepayment, isAccountTransfer, holidayDetailDto, isHolidayValidationDone);
LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, transactionDate,
transactionAmount, paymentDetail, noteText, txnExternalId, isRecoveryRepayment, isAccountTransfer, holidayDetailDto,
isHolidayValidationDone);
// Update loan transaction on repayment.
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
loanCollateralManagement.setLoanTransactionData(loanTransaction);
ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement();
if (loan.status().isClosed()) {
loanCollateralManagement.setIsReleased(Integer.valueOf(1));
BigDecimal quantity = loanCollateralManagement.getQuantity();
clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(quantity));
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
}
}
this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements);
}
return commandProcessingResultBuilder.withCommandId(command.commandId()) //
.withLoanId(loanId) //
@@ -1299,9 +1342,26 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
}
this.loanAccountDomainService.recalculateAccruals(loan);
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BusinessEvents.LOAN_CLOSE,
constructEntityMap(BusinessEntity.LOAN, loan));
// Update loan transaction on repayment.
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement();
if (loan.status().isClosed()) {
loanCollateralManagement.setIsReleased(Integer.valueOf(1));
BigDecimal quantity = loanCollateralManagement.getQuantity();
clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(quantity));
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
}
}
this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements);
}
// disable all active standing instructions linked to the loan
this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan);
@@ -1353,6 +1413,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
// disable all active standing instructions linked to the loan
this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan);
// Update loan transaction on repayment.
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) {
ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement();
if (loan.status().isClosed()) {
loanCollateralManagement.setIsReleased(Integer.valueOf(1));
BigDecimal quantity = loanCollateralManagement.getQuantity();
clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(quantity));
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
}
}
this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(loanId) //
@@ -19,3 +19,48 @@
ALTER TABLE `m_loan`
ADD COLUMN `loan_type_enum` SMALLINT NOT NULL AFTER `loan_status_id`;
-- create collateral management table
CREATE TABLE IF NOT EXISTS `m_collateral_management` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`quality` varchar(40) NOT NULL,
`base_price` decimal(20,5) NOT NULL,
`unit_type` varchar(10) NOT NULL,
`pct_to_base` decimal(20,5) NOT NULL,
`currency` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `fkCurrencyCode` (`currency`),
CONSTRAINT `fkCurrencyCode` FOREIGN KEY (`currency`) REFERENCES `m_currency` (`id`) ON DELETE CASCADE
);
-- create client collateral management
CREATE TABLE IF NOT EXISTS `m_client_collateral_management` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`quantity` decimal(20,5) NOT NULL,
`client_id` bigint(20) DEFAULT NULL,
`collateral_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `fkClient` (`client_id`),
KEY `fkCollateral` (`collateral_id`),
CONSTRAINT `fkClient` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fkCollateral` FOREIGN KEY (`collateral_id`) REFERENCES `m_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
-- create loan collateral management
CREATE TABLE IF NOT EXISTS `m_loan_collateral_management` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`quantity` decimal(20,5) NOT NULL,
`loan_id` bigint(20) DEFAULT NULL,
`client_collateral_id` bigint(20) DEFAULT NULL,
`is_released` tinyint(4) DEFAULT '0',
`transaction_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `fkLoan` (`loan_id`),
KEY `fkTransaction` (`transaction_id`),
KEY `fkClientCollateral` (`client_collateral_id`),
CONSTRAINT `fkClientCollateral` FOREIGN KEY (`client_collateral_id`) REFERENCES `m_client_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fkLoan` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fkTransaction` FOREIGN KEY (`transaction_id`) REFERENCES `m_loan_transaction` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
@@ -0,0 +1,73 @@
--
-- 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.
--
-- create collateral management table
CREATE TABLE IF NOT EXISTS `m_collateral_management` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`quality` varchar(40) NOT NULL,
`base_price` decimal(20,5) NOT NULL,
`unit_type` varchar(10) NOT NULL,
`pct_to_base` decimal(20,5) NOT NULL,
`currency` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `fkCurrencyCode` (`currency`),
CONSTRAINT `fkCurrencyCode` FOREIGN KEY (`currency`) REFERENCES `m_currency` (`id`) ON DELETE CASCADE
);
-- create client collateral management
CREATE TABLE IF NOT EXISTS `m_client_collateral_management` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`quantity` decimal(20,5) NOT NULL,
`client_id` bigint(20) DEFAULT NULL,
`collateral_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `fkClient` (`client_id`),
KEY `fkCollateral` (`collateral_id`),
CONSTRAINT `fkClient` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fkCollateral` FOREIGN KEY (`collateral_id`) REFERENCES `m_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
-- create loan collateral management
CREATE TABLE IF NOT EXISTS `m_loan_collateral_management` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`quantity` decimal(20,5) NOT NULL,
`loan_id` bigint(20) DEFAULT NULL,
`client_collateral_id` bigint(20) DEFAULT NULL,
`is_released` tinyint(4) DEFAULT '0',
`transaction_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `fkLoan` (`loan_id`),
KEY `fkTransaction` (`transaction_id`),
KEY `fkClientCollateral` (`client_collateral_id`),
CONSTRAINT `fkClientCollateral` FOREIGN KEY (`client_collateral_id`) REFERENCES `m_client_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fkLoan` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fkTransaction` FOREIGN KEY (`transaction_id`) REFERENCES `m_loan_transaction` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO `m_permission`
(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`) VALUES
('portfolio', 'CREATE_CLIENT_COLLATERAL_PRODUCT', 'CLIENT_COLLATERAL_PRODUCT', 'CREATE', '0'),
('portfolio', 'CREATE_COLLATERAL_PRODUCT', 'COLLATERAL_PRODUCT', 'CREATE', '0'),
('portfolio', 'DELETE_CLIENT_COLLATERAL_PRODUCT', 'CLIENT_COLLATERAL_PRODUCT', 'DELETE', '0'),
('portfolio', 'DELETE_COLLATERAL_PRODUCT', 'COLLATERAL_PRODUCT', 'DELETE', '0'),
('portfolio', 'DELETE_LOAN_COLLATERAL_PRODUCT', 'LOAN_COLLATERAL_PRODUCT', 'DELETE', '0'),
('portfolio', 'UPDATE_CLIENT_COLLATERAL_PRODUCT', 'CLIENT_COLLATERAL_PRODUCT', 'UPDATE', '0'),
('portfolio', 'UPDATE_COLLATERAL_PRODUCT', 'COLLATERAL_PRODUCT', 'UPDATE', '0');
@@ -23,12 +23,15 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.CenterDomain;
import org.apache.fineract.integrationtests.common.CenterHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.OfficeHelper;
@@ -355,15 +358,17 @@ public class AccountNumberPreferencesTest {
/* Create Client with Client Type */
this.clientId = ClientHelper.createClientForAccountPreference(this.requestSpec, this.responseSpec, this.clientCodeValueId,
"clientId");
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, this.clientId);
Assertions.assertNotNull(clientId);
// Assertions.assertNotNull(clientId);
clientAccountNo = (String) ClientHelper.getClient(this.requestSpec, this.responseSpec, this.clientId.toString(), "accountNo");
this.validateAccountNumberLengthAndStartsWithPrefix(clientAccountNo, this.clientCodeValueName);
} else if (clientPrefixName.equals(this.officeName)) {
this.clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, this.clientId);
// Assertions.assertNotNull(clientId);
clientAccountNo = (String) ClientHelper.getClient(requestSpec, responseSpec, this.clientId.toString(), "accountNo");
String officeName = (String) ClientHelper.getClient(requestSpec, responseSpec, this.clientId.toString(), "officeName");
this.validateAccountNumberLengthAndStartsWithPrefix(clientAccountNo, officeName);
@@ -393,17 +398,34 @@ public class AccountNumberPreferencesTest {
LOG.info("Successfully created loan product (ID: {} )", this.loanProductId);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
private void createAndValidateLoanEntity(Boolean isAccountPreferenceSetUp) {
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
this.clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments)
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments()
.withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod).withLoanTermFrequencyAsMonths()
.withSubmittedOnDate(dateString).withExpectedDisbursementDate(dateString).withPrincipalGrace("2").withInterestGrace("2")
.build(this.clientId.toString(), this.loanProductId.toString(), null);
.withCollaterals(collaterals).build(this.clientId.toString(), this.loanProductId.toString(), null);
LOG.info("Loan Application :{}", loanApplicationJSON);
@@ -25,9 +25,12 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.OfficeHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -474,6 +477,14 @@ public class AccountTransferTest {
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("8,000.00") //
.withLoanTermFrequency("4") //
@@ -487,7 +498,18 @@ public class AccountTransferTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("10 January 2013") //
.withSubmittedOnDate("10 January 2013") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
}
@@ -25,6 +25,7 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@@ -39,6 +40,7 @@ import java.util.List;
import java.util.Locale;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -138,7 +140,16 @@ public class AccountingScenarioIntegrationTest {
overpaymentAccount);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(),
collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -238,14 +249,14 @@ public class AccountingScenarioIntegrationTest {
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(LP_PRINCIPAL.toString())
.withLoanTermFrequency(LOAN_TERM_FREQUENCY).withLoanTermFrequencyAsMonths().withNumberOfRepayments(LP_REPAYMENTS)
.withRepaymentEveryAfter(LP_REPAYMENT_PERIOD).withRepaymentFrequencyTypeAsMonths()
.withInterestRatePerPeriod(LP_INTEREST_RATE).withInterestTypeAsFlatBalance().withAmortizationTypeAsEqualPrincipalPayments()
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withExpectedDisbursementDate(EXPECTED_DISBURSAL_DATE)
.withSubmittedOnDate(LOAN_APPLICATION_SUBMISSION_DATE).withLoanType(INDIVIDUAL_LOAN)
.withSubmittedOnDate(LOAN_APPLICATION_SUBMISSION_DATE).withLoanType(INDIVIDUAL_LOAN).withCollaterals(collaterals)
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -378,7 +389,8 @@ public class AccountingScenarioIntegrationTest {
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
Integer clientId = ClientHelper.createClient(requestSpec, responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientId);
// Assertions.assertNotNull(clientId);
Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, assetAccount, incomeAccount, expenseAccount,
liabilityAccount);
@@ -456,7 +468,7 @@ public class AccountingScenarioIntegrationTest {
final String INTEREST_POSTED_DATE = dateFormat.format(todaysDate.getTime());
Integer clientId = ClientHelper.createClient(requestSpec, responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientId);
Integer recurringDepositProductId = createRecurringDepositProduct(VALID_FROM, VALID_TO, assetAccount, liabilityAccount,
incomeAccount, expenseAccount);
@@ -564,7 +576,16 @@ public class AccountingScenarioIntegrationTest {
overpaymentAccount);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(),
collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -677,7 +698,16 @@ public class AccountingScenarioIntegrationTest {
overpaymentAccount);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(),
collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -721,6 +751,17 @@ public class AccountingScenarioIntegrationTest {
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
@Test
public void checkPeriodicAccrualAccountingTillCurrentDateFlow() throws InterruptedException, ParseException {
final Account assetAccount = this.accountHelper.createAssetAccount();
@@ -732,7 +773,16 @@ public class AccountingScenarioIntegrationTest {
overpaymentAccount);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(),
collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals);
final float FEE_PORTION = 50.0f;
final float PENALTY_PORTION = 100.0f;
@@ -821,7 +871,16 @@ public class AccountingScenarioIntegrationTest {
overpaymentAccount);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(),
collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals);
final float FEE_PORTION = 50.0f;
final float PENALTY_PORTION = 100.0f;
@@ -942,7 +1001,16 @@ public class AccountingScenarioIntegrationTest {
overpaymentAccount);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(),
collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -31,7 +31,6 @@ import org.apache.fineract.integrationtests.common.AuditHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.OfficeHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -77,7 +76,8 @@ public class AuditIntegrationTest {
// When Client is created: Count should be "1"
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
auditsRecieved = auditHelper.getAuditDetails(clientId, "CREATE", "CLIENT");
auditHelper.verifyOneAuditOnly(auditsRecieved, clientId, "CREATE", "CLIENT");
@@ -32,6 +32,8 @@ import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.integrationtests.common.BatchHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
@@ -202,6 +204,15 @@ public class BatchApiTest {
.withInterestTypeAsDecliningBalance() //
.currencyDetails("0", "100").build(null);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON);
// Create a createClient Request
@@ -211,7 +222,7 @@ public class BatchApiTest {
final BatchRequest br2 = BatchHelper.activateClientRequest(4719L, 4718L);
// Create a ApplyLoan Request
final BatchRequest br3 = BatchHelper.applyLoanRequest(4720L, 4719L, productId);
final BatchRequest br3 = BatchHelper.applyLoanRequest(4720L, 4719L, productId, clientCollateralId);
final List<BatchRequest> batchRequests = new ArrayList<>();
@@ -293,6 +304,15 @@ public class BatchApiTest {
.withInterestTypeAsDecliningBalance() //
.currencyDetails("0", "100").build(null);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON);
// Create a createClient Request
@@ -302,7 +322,7 @@ public class BatchApiTest {
final BatchRequest br2 = BatchHelper.activateClientRequest(4723L, 4722L);
// Create a ApplyLoan Request
final BatchRequest br3 = BatchHelper.applyLoanRequest(4724L, 4723L, productId);
final BatchRequest br3 = BatchHelper.applyLoanRequest(4724L, 4723L, productId, clientCollateralId);
// Create a Collect Charges Request
final BatchRequest br4 = BatchHelper.collectChargesRequest(4725L, 4724L);
@@ -343,6 +363,15 @@ public class BatchApiTest {
.withInterestTypeAsDecliningBalance() //
.currencyDetails("0", "100").build(null);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON);
// Create a createClient Request
@@ -352,7 +381,7 @@ public class BatchApiTest {
final BatchRequest br2 = BatchHelper.activateClientRequest(4731L, 4730L);
// Create a ApplyLoan Request
final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId);
final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId, clientCollateralId);
// Create a approveLoan Request
final BatchRequest br4 = BatchHelper.approveLoanRequest(4733L, 4732L);
@@ -434,6 +463,15 @@ public class BatchApiTest {
.withInterestTypeAsDecliningBalance() //
.currencyDetails("0", "100").build(null);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON);
// Create a createClient Request
@@ -443,7 +481,7 @@ public class BatchApiTest {
final BatchRequest br2 = BatchHelper.activateClientRequest(4731L, 4730L);
// Create a ApplyLoan Request
final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId);
final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId, clientCollateralId);
// Create a approveLoan Request
final BatchRequest br4 = BatchHelper.approveLoanRequest(4733L, 4732L);
@@ -488,13 +526,22 @@ public class BatchApiTest {
.withInterestTypeAsDecliningBalance() //
.currencyDetails("0", "100").build(null);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON);
// Create a createClient Request
final BatchRequest br1 = BatchHelper.createActiveClientRequest(4740L, "");
// Create a ApplyLoan Request
final BatchRequest br2 = BatchHelper.applyLoanRequest(4742L, 4740L, productId);
final BatchRequest br2 = BatchHelper.applyLoanRequest(4742L, 4740L, productId, clientCollateralId);
// Create a approveLoan Request
final BatchRequest br3 = BatchHelper.approveLoanRequest(4743L, 4742L);
@@ -29,6 +29,7 @@ import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.integrationtests.common.BatchHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
@@ -119,7 +120,14 @@ public class BatchRequestsIntegrationTest {
// Select a few clients from created group at random
Integer selClientsCount = (int) Math.ceil(Math.random() * clientsCount) + 2;
for (int i = 0; i < selClientsCount; i++) {
BatchRequest br = BatchHelper.applyLoanRequest((long) selClientsCount, null, loanProductID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientIDs[(int) Math.floor(Math.random() * (clientsCount - 1))]), collateralId);
Assertions.assertNotNull(clientCollateralId);
BatchRequest br = BatchHelper.applyLoanRequest((long) selClientsCount, null, loanProductID, clientCollateralId);
br.setBody(br.getBody().replace("$.clientId", String.valueOf(clientIDs[(int) Math.floor(Math.random() * (clientsCount - 1))])));
batchRequests.add(br);
}
@@ -0,0 +1,78 @@
/**
* 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.integrationtests;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.util.HashMap;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientCollateralIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(ClientCollateralIntegrationTest.class);
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
@BeforeEach
public void setup() {
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
}
@Test
public void createClientCollateralTest() {
LOG.info("-------------------------Creating Client Collateral---------------------------");
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
}
@Test
public void updateClientCollateral() {
LOG.info("-------------------------Updating Client Collateral---------------------------");
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
final HashMap changes = CollateralManagementHelper.updateClientCollateral(this.requestSpec, this.responseSpec, clientCollateralId);
Assertions.assertEquals("1", changes.get("quantity").toString());
}
}
@@ -41,6 +41,7 @@ import java.util.List;
import java.util.Map;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
@@ -103,11 +104,19 @@ public class ClientLoanIntegrationTest {
@Test
public void checkClientLoanCreateAndDisburseFlow() {
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
List<HashMap> collaterals = new ArrayList<>();
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, NONE);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00", collaterals);
final ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec,
loanID);
verifyLoanRepaymentSchedule(loanSchedule);
@@ -116,11 +125,18 @@ public class ClientLoanIntegrationTest {
@Test
public void testLoanCharges_DISBURSEMENT_FEE() {
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer loanProductID = createLoanProduct(false, NONE);
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
List<HashMap> collaterals = new ArrayList<>();
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
List<HashMap> charges = new ArrayList<>();
Integer flatDisbursement = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper.getLoanDisbursementJSON());
@@ -134,7 +150,7 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1"));
addCharges(charges, interestPercentage, "1", null);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -180,7 +196,7 @@ public class ClientLoanIntegrationTest {
validateNumberForEqual("654.24", String.valueOf(disbursementDetail.get("feeChargesDue")));
this.loanTransactionHelper.updateLoan(loanID,
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), null));
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -192,7 +208,7 @@ public class ClientLoanIntegrationTest {
validateNumberForEqual("570.2", String.valueOf(disbursementDetail.get("feeChargesDue")));
this.loanTransactionHelper.updateLoan(loanID,
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flatDisbursement, "1"), null));
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flatDisbursement, "1"), null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -204,7 +220,7 @@ public class ClientLoanIntegrationTest {
charges.clear();
addCharges(charges, flatDisbursement, "100", null);
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null));
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -240,7 +256,16 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1"));
addCharges(charges, interestPercentage, "1", null);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -301,7 +326,16 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false));
addCharges(charges, interestPercentage, "1", "29 September 2011");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -348,8 +382,8 @@ public class ClientLoanIntegrationTest {
final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
MINIMUM_OPENING_BALANCE);
this.loanTransactionHelper.updateLoan(loanID,
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), String.valueOf(savingsId)));
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null),
String.valueOf(savingsId), collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -361,7 +395,7 @@ public class ClientLoanIntegrationTest {
validateNumberForEqual("570.2", String.valueOf(firstInstallment.get("feeChargesDue")));
this.loanTransactionHelper.updateLoan(loanID,
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null));
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -373,7 +407,7 @@ public class ClientLoanIntegrationTest {
charges.clear();
addCharges(charges, flat, "100", "29 September 2011");
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null));
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -461,7 +495,15 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false));
addCharges(charges, interestPercentage, "1", "29 September 2011");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -553,8 +595,8 @@ public class ClientLoanIntegrationTest {
final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
MINIMUM_OPENING_BALANCE);
this.loanTransactionHelper.updateLoan(loanID,
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), String.valueOf(savingsId)));
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null),
String.valueOf(savingsId), collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -581,7 +623,7 @@ public class ClientLoanIntegrationTest {
validateChargeExcludePrecission(flat, loanCharges, "100.0", "400", "0.0", "0.0");
this.loanTransactionHelper.updateLoan(loanID,
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null));
updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -608,7 +650,7 @@ public class ClientLoanIntegrationTest {
charges.clear();
addCharges(charges, flat, "50", "29 September 2011");
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null));
this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null, collaterals));
loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -715,7 +757,15 @@ public class ClientLoanIntegrationTest {
final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
MINIMUM_OPENING_BALANCE);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, savingsId.toString(), "12,000.00");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, savingsId.toString(), "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -760,7 +810,16 @@ public class ClientLoanIntegrationTest {
tranches.add(createTrancheDetail("01 March 2014", "25000"));
tranches.add(createTrancheDetail("23 April 2014", "20000"));
final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, null, "45,000.00", tranches);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, null, "45,000.00", tranches, collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -803,8 +862,17 @@ public class ClientLoanIntegrationTest {
tranches.add(createTrancheDetail("01 March 2014", "25000"));
tranches.add(createTrancheDetail("23 April 2014", "20000"));
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, savingsId.toString(), "45,000.00",
tranches);
tranches, collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -938,7 +1006,8 @@ public class ClientLoanIntegrationTest {
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment) {
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment,
List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("10000000.00") //
@@ -953,12 +1022,12 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withPrincipalGrace(graceOnPrincipalPayment).withExpectedDisbursementDate("02 June 2014") //
.withSubmittedOnDate("02 June 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
final String savingsId, String principal) {
final String savingsId, String principal, List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
@@ -973,12 +1042,12 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011") //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
final String savingsId, String principal, List<HashMap> tranches) {
final String savingsId, String principal, List<HashMap> tranches, List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
@@ -992,14 +1061,14 @@ public class ClientLoanIntegrationTest {
.withInterestTypeAsDecliningBalance() //
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("01 March 2014") //
.withTranches(tranches) //
.withCollaterals(collaterals).withTranches(tranches) //
.withSubmittedOnDate("01 March 2014") //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private String updateLoanJson(final Integer clientID, final Integer loanProductID, List<HashMap> charges, String savingsId) {
private String updateLoanJson(final Integer clientID, final Integer loanProductID, List<HashMap> charges, String savingsId,
List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("10,000.00") //
@@ -1014,12 +1083,12 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011") //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return loanApplicationJSON;
}
private Integer applyForLoanApplicationWithPaymentStrategy(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
final String savingsId, String principal, final String repaymentStrategy) {
final String savingsId, String principal, final String repaymentStrategy, final List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
@@ -1035,12 +1104,13 @@ public class ClientLoanIntegrationTest {
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011") //
.withwithRepaymentStrategy(repaymentStrategy) //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private Integer applyForLoanApplicationWithPaymentStrategyAndPastMonth(final Integer clientID, final Integer loanProductID,
List<HashMap> charges, final String savingsId, String principal, final String repaymentStrategy, final int month) {
List<HashMap> charges, final String savingsId, String principal, final String repaymentStrategy, final int month,
List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
Calendar fourMonthsfromNowCalendar = Calendar.getInstance(Utils.getTimeZoneOfTenant());
@@ -1062,7 +1132,7 @@ public class ClientLoanIntegrationTest {
.withExpectedDisbursementDate(fourMonthsfromNow) //
.withSubmittedOnDate(fourMonthsfromNow) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -1203,6 +1273,10 @@ public class ClientLoanIntegrationTest {
charges.add(charges(chargeId, amount, duedate));
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap charges(Integer chargeId, String amount, String duedate) {
HashMap charge = new HashMap(2);
charge.put("chargeId", chargeId.toString());
@@ -1213,6 +1287,13 @@ public class ClientLoanIntegrationTest {
return charge;
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
private HashMap getloanCharge(Integer chargeId, List<HashMap> charges) {
HashMap charge = null;
for (HashMap loancharge : charges) {
@@ -1282,8 +1363,17 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -1462,8 +1552,17 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -1642,8 +1741,18 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -1819,9 +1928,18 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, ACCRUAL_UPFRONT, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -2016,9 +2134,18 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, ACCRUAL_UPFRONT, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -2205,9 +2332,17 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, ACCRUAL_UPFRONT, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -2399,9 +2534,17 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, ACCRUAL_PERIODIC, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -2591,9 +2734,17 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, ACCRUAL_PERIODIC, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -2784,9 +2935,18 @@ public class ClientLoanIntegrationTest {
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct(false, ACCRUAL_PERIODIC, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -2954,8 +3114,17 @@ public class ClientLoanIntegrationTest {
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct("100", "0", LoanProductTestBuilder.DEFAULT_STRATEGY);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, collaterals);
final ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec,
loanID);
verifyLoanRepaymentScheduleForEqualPrincipal(loanSchedule);
@@ -2968,8 +3137,17 @@ public class ClientLoanIntegrationTest {
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanProductID = createLoanProduct("100", "0", LoanProductTestBuilder.DEFAULT_STRATEGY);
final Integer loanID = applyForLoanApplication(clientID, loanProductID, "5");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, "5", collaterals);
final ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec,
loanID);
verifyLoanRepaymentScheduleForEqualPrincipalWithGrace(loanSchedule);
@@ -2997,8 +3175,17 @@ public class ClientLoanIntegrationTest {
*/
final String savingsId = null;
final String principal = "12,000.00";
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplicationWithPaymentStrategy(clientID, loanProductID, null, savingsId, principal,
LoanApplicationTestBuilder.RBI_INDIA_STRATEGY);
LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -4321,6 +4508,15 @@ public class ClientLoanIntegrationTest {
final String disbursementDate, final String repaymentStrategy, final List<HashMap> charges, final String graceOnInterestPayment,
final String graceOnPrincipalPayment) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
List<HashMap> collaterals = new ArrayList<>();
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("10000.00") //
.withLoanTermFrequency("4") //
@@ -4338,7 +4534,7 @@ public class ClientLoanIntegrationTest {
.withPrincipalGrace(graceOnPrincipalPayment) //
.withInterestGrace(graceOnInterestPayment)//
.withCharges(charges)//
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -4415,8 +4611,16 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
addCharges(charges, flatInstallmentFee, "50", null);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, charges, savingsId,
principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4);
principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4, collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -4590,8 +4794,17 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
addCharges(charges, flatInstallmentFee, "50", null);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, charges, savingsId,
principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4);
principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4, collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -4776,8 +4989,17 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
addCharges(charges, flatInstallmentFee, "50", null);
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, charges, null, principal,
LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4);
LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4, collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
@@ -4999,7 +5221,15 @@ public class ClientLoanIntegrationTest {
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", true));
addCharges(charges, flatAmountChargeTwo, "100", "15 December 2011");
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "10,000.00");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "10,000.00", collaterals);
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -5284,6 +5514,14 @@ public class ClientLoanIntegrationTest {
private Integer applyForLoanApplicationWithProductConfigurationAsTrue(final Integer clientID, final Integer loanProductID,
String principal) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
List<HashMap> collaterals = new ArrayList<>();
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
.withRepaymentEveryAfter("1") //
@@ -5295,13 +5533,21 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("01 March 2014") //
.withSubmittedOnDate("01 March 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private Integer applyForLoanApplicationWithProductConfigurationAsFalse(final Integer clientID, final Integer loanProductID,
String principal) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
List<HashMap> collaterals = new ArrayList<>();
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(principal)
@@ -5319,7 +5565,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("01 March 2014") //
.withSubmittedOnDate("01 March 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -88,7 +88,8 @@ public class ClientSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -131,7 +132,8 @@ public class ClientSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = "5000";
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -178,7 +180,8 @@ public class ClientSavingsIntegrationTest {
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = "1000.0";
final String enforceMinRequiredBalance = "true";
@@ -221,7 +224,8 @@ public class ClientSavingsIntegrationTest {
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = "1500.0";
final String openningBalance = "1600";
@@ -288,7 +292,8 @@ public class ClientSavingsIntegrationTest {
new ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -331,7 +336,8 @@ public class ClientSavingsIntegrationTest {
new ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -376,7 +382,8 @@ public class ClientSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -404,7 +411,8 @@ public class ClientSavingsIntegrationTest {
new ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -505,7 +513,8 @@ public class ClientSavingsIntegrationTest {
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, erroResponseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -670,7 +679,8 @@ public class ClientSavingsIntegrationTest {
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
@@ -802,7 +812,8 @@ public class ClientSavingsIntegrationTest {
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
@@ -1053,7 +1064,8 @@ public class ClientSavingsIntegrationTest {
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
@@ -1315,7 +1327,8 @@ public class ClientSavingsIntegrationTest {
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
@@ -1483,7 +1496,8 @@ public class ClientSavingsIntegrationTest {
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
@@ -1635,7 +1649,8 @@ public class ClientSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -1684,7 +1699,8 @@ public class ClientSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -1735,6 +1751,7 @@ public class ClientSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
@@ -1935,7 +1952,8 @@ public class ClientSavingsIntegrationTest {
new ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
@@ -2055,7 +2073,9 @@ public class ClientSavingsIntegrationTest {
// ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = "500";
final String enforceMinRequiredBalance = "false";
@@ -30,7 +30,6 @@ import java.util.List;
import java.util.Random;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -53,7 +52,8 @@ public class ClientTest {
public void testClientStatus() {
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
// Assertions.assertNotNull(clientId);
HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));
ClientStatusChecker.verifyClientIsActive(status);
@@ -85,7 +85,8 @@ public class ClientTest {
public void testClientAsPersonStatus() {
final Integer clientId = ClientHelper.createClientAsPerson(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
// Assertions.assertNotNull(clientId);
HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));
ClientStatusChecker.verifyClientIsActive(status);
@@ -117,7 +118,8 @@ public class ClientTest {
public void testClientAsEntityStatus() {
final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
// Assertions.assertNotNull(clientId);
HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));
ClientStatusChecker.verifyClientIsActive(status);
@@ -66,7 +66,8 @@ public class ClientUndoRejectAndWithdrawalIntegrationTest {
// CREATE CLIENT
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
// Assertions.assertNotNull(clientId);
// GET CLIENT STATUS
HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));
@@ -0,0 +1,67 @@
/**
* 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.integrationtests;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CollateralProductIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(CollateralProductIntegrationTest.class);
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private LoanTransactionHelper loanTransactionHelper;
@BeforeEach
public void setup() {
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
}
@Test
public void createCollateralProductTest() {
LOG.info("-------------------------Creating Collateral Product---------------------------");
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
}
@Test
public void updateCollateralProductTest() {
LOG.info("-------------------------Updating Collateral Product---------------------------");
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer resourceId = CollateralManagementHelper.updateCollateralProduct(this.requestSpec, this.responseSpec, collateralId);
Assertions.assertEquals(collateralId, resourceId);
}
}
@@ -23,18 +23,24 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -115,6 +121,13 @@ public class ConcurrencyIntegrationTest {
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String principal) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
.withLoanTermFrequency("4") //
@@ -128,10 +141,21 @@ public class ConcurrencyIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
public static class LoanRepaymentExecutor implements Runnable {
private final Integer loanId;
@@ -25,12 +25,14 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -225,6 +227,16 @@ public class GroupLoanIntegrationTest {
private HashMap<String, Integer> applyForGlimApplication(final Integer clientID, final Integer groupID, final Integer loanProductID) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String GlimApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("12,000.00") //
.withLoanTermFrequency("4") //
@@ -238,11 +250,22 @@ public class GroupLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011").withLoanType("glim").withtotalLoan("10000").withParentAccount("1")
.build(clientID.toString(), groupID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), groupID.toString(), loanProductID.toString(), null);
LOG.info(GlimApplicationJSON);
return this.loanTransactionHelper.getGlimId(GlimApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal amount) {
collaterals.add(collaterals(collateralId, amount));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal amount) {
HashMap<String, String> collateral = new HashMap<String, String>(1);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("amount", amount.toString());
return collateral;
}
private void verifyLoanRepaymentSchedule(final ArrayList<HashMap> loanSchedule) {
LOG.info("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
@@ -82,6 +82,7 @@ public class GroupSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
@@ -285,6 +286,7 @@ public class GroupSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
@@ -341,7 +343,8 @@ public class GroupSavingsIntegrationTest {
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -389,7 +392,8 @@ public class GroupSavingsIntegrationTest {
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -422,7 +426,8 @@ public class GroupSavingsIntegrationTest {
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -455,7 +460,8 @@ public class GroupSavingsIntegrationTest {
new ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -506,7 +512,8 @@ public class GroupSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -540,7 +547,8 @@ public class GroupSavingsIntegrationTest {
new ResponseSpecBuilder().build());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -644,7 +652,8 @@ public class GroupSavingsIntegrationTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientID);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true);
Assertions.assertNotNull(groupID);
@@ -26,8 +26,12 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
@@ -61,7 +65,6 @@ public class GroupTest {
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
}
@Test
@@ -104,6 +107,8 @@ public class GroupTest {
// create client and add client to group
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString());
GroupHelper.verifyGroupMembers(this.requestSpec, this.responseSpec, groupID, clientID);
@@ -158,6 +163,14 @@ public class GroupTest {
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String principal) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
.withLoanTermFrequency("4") //
@@ -171,8 +184,19 @@ public class GroupTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2014") //
.withSubmittedOnDate("20 September 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
}
@@ -25,16 +25,19 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -243,16 +246,43 @@ public class LoanApplicationApprovalTest {
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) {
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5")
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1")
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012")
.withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).withSubmittedOnDate("02 April 2012")
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplication);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
List<HashMap> tranches) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(principal)
@@ -267,7 +297,7 @@ public class LoanApplicationApprovalTest {
.withTranches(tranches) //
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 March 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -23,10 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
@@ -128,9 +130,27 @@ public class LoanApplicationUndoLastTrancheTest {
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
List<HashMap> tranches) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(principal)
@@ -145,7 +165,7 @@ public class LoanApplicationUndoLastTrancheTest {
.withTranches(tranches) //
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 March 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -23,9 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
@@ -100,11 +103,30 @@ public class LoanDisbursalDateValidationTest {
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) {
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5")
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1")
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("01 March 2014")
.withSubmittedOnDate("26 February 2014").build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).withSubmittedOnDate("26 February 2014")
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplication);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
}
@@ -25,18 +25,21 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanDisbursementTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -309,6 +312,14 @@ public class LoanDisbursementDetailsIntegrationTest {
List<HashMap> tranches, final String installmentAmount) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(proposedAmount)
@@ -325,7 +336,7 @@ public class LoanDisbursementDetailsIntegrationTest {
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 June 2015") //
.withAmortizationTypeAsEqualInstallments() //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -434,6 +445,13 @@ public class LoanDisbursementDetailsIntegrationTest {
private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
List<HashMap> tranches) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(principal)
@@ -448,9 +466,20 @@ public class LoanDisbursementDetailsIntegrationTest {
.withTranches(tranches) //
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 March 2014") //
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
}
@@ -25,6 +25,7 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -32,12 +33,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -95,9 +98,17 @@ public class LoanRepaymentRescheduleAtDisbursementTest {
approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 March 2015", "5000"));
approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 May 2015", "5000"));
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientID), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
// APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate,
LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0), createTranches);
LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0), createTranches, collaterals);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -134,6 +145,17 @@ public class LoanRepaymentRescheduleAtDisbursementTest {
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
private void verifyLoanRepaymentSchedule(final HashMap firstInstallement, final Map<String, Object> expectedvalues) {
assertEquals(expectedvalues.get("dueDate"), firstInstallement.get("dueDate"));
@@ -195,16 +217,18 @@ public class LoanRepaymentRescheduleAtDisbursementTest {
}
private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID,
final String disbursementDate, final String repaymentStrategy, final List<HashMap> charges, List<HashMap> tranches) {
final String disbursementDate, final String repaymentStrategy, final List<HashMap> charges, List<HashMap> tranches,
final List<HashMap> collaterals) {
final String graceOnInterestPayment = null;
final String graceOnPrincipalPayment = null;
return applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate, repaymentStrategy, charges,
graceOnInterestPayment, graceOnPrincipalPayment, tranches);
graceOnInterestPayment, graceOnPrincipalPayment, tranches, collaterals);
}
private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID,
final String disbursementDate, final String repaymentStrategy, final List<HashMap> charges, final String graceOnInterestPayment,
final String graceOnPrincipalPayment, List<HashMap> tranches) {
final String graceOnPrincipalPayment, List<HashMap> tranches, List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("10000.00") //
@@ -222,7 +246,7 @@ public class LoanRepaymentRescheduleAtDisbursementTest {
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withCharges(charges)//
.withCollaterals(collaterals).withCharges(charges)//
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -26,10 +26,13 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -38,6 +41,7 @@ import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanRescheduleRequestTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -160,12 +164,21 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
private void createLoanEntity() {
LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
this.clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments)
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments()
.withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod)
.withInterestTypeAsDecliningBalance().withSubmittedOnDate(dateString).withExpectedDisbursementDate(dateString)
.withPrincipalGrace("2").withInterestGrace("2").build(this.clientId.toString(), this.loanProductId.toString(), null);
.withCollaterals(collaterals).withPrincipalGrace("2").withInterestGrace("2")
.build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -175,6 +188,17 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
this.disburseLoan();
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
/**
* approve the loan application
**/
@@ -26,14 +26,19 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanRescheduleRequestTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -112,13 +117,19 @@ public class LoanRescheduleRequestTest {
**/
private void createLoanEntity() {
LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
this.clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments)
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments()
.withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod).withLoanTermFrequencyAsMonths()
.withSubmittedOnDate(dateString).withExpectedDisbursementDate(dateString).withPrincipalGrace("2").withInterestGrace("2")
.build(this.clientId.toString(), this.loanProductId.toString(), null);
.withCollaterals(collaterals).build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -128,6 +139,17 @@ public class LoanRescheduleRequestTest {
this.disburseLoan();
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
/**
* approve the loan application
**/
@@ -26,6 +26,7 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -38,6 +39,7 @@ import org.apache.fineract.integrationtests.common.CalendarHelper;
import org.apache.fineract.integrationtests.common.CenterDomain;
import org.apache.fineract.integrationtests.common.CenterHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.OfficeHelper;
@@ -109,6 +111,15 @@ public class LoanReschedulingWithinCenterTest {
final String recalculationRestFrequencyDate = "01 January 2012";
final boolean isMultiTrancheLoan = false;
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientId), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
// CREATE LOAN MULTIDISBURSAL PRODUCT WITH INTEREST RECALCULATION
final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY,
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
@@ -118,7 +129,8 @@ public class LoanReschedulingWithinCenterTest {
// APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION
final Integer loanId = applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, loanProductID, disbursalDate,
recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0), null);
recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0), null,
collaterals);
// Test for loan account is created
Assertions.assertNotNull(loanId);
@@ -153,6 +165,17 @@ public class LoanReschedulingWithinCenterTest {
assertEquals("90.82", String.valueOf(interestDue));
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal amount) {
collaterals.add(collaterals(collateralId, amount));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal amount) {
HashMap<String, String> collateral = new HashMap<String, String>(1);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("amount", amount.toString());
return collateral;
}
private void associateClientsToGroup(Integer groupId, Integer clientId) {
// Associate client to the group
GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupId.toString(), clientId.toString());
@@ -244,10 +267,19 @@ public class LoanReschedulingWithinCenterTest {
approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail(disbursementDate, "5000"));
approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail(secondDisbursement, "5000"));
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
String.valueOf(clientId), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
// APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, loanProductID,
disbursementDate, recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0),
createTranches);
createTranches, collaterals);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
// VALIDATE THE LOAN STATUS
@@ -340,19 +372,20 @@ public class LoanReschedulingWithinCenterTest {
@SuppressWarnings("rawtypes")
private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, Integer groupId, Integer calendarId,
final Integer loanProductID, final String disbursementDate, final String restStartDate, final String repaymentStrategy,
final List<HashMap> charges, List<HashMap> tranches) {
final List<HashMap> charges, List<HashMap> tranches, List<HashMap> collaterals) {
final String graceOnInterestPayment = null;
final String compoundingStartDate = null;
final String graceOnPrincipalPayment = null;
return applyForLoanApplicationForInterestRecalculation(clientID, groupId, calendarId, loanProductID, disbursementDate,
restStartDate, compoundingStartDate, repaymentStrategy, charges, graceOnInterestPayment, graceOnPrincipalPayment, tranches);
restStartDate, compoundingStartDate, repaymentStrategy, charges, graceOnInterestPayment, graceOnPrincipalPayment, tranches,
collaterals);
}
@SuppressWarnings({ "rawtypes", "unused" })
private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, Integer groupId, Integer calendarId,
final Integer loanProductID, final String disbursementDate, final String restStartDate, final String compoundingStartDate,
final String repaymentStrategy, final List<HashMap> charges, final String graceOnInterestPayment,
final String graceOnPrincipalPayment, List<HashMap> tranches) {
final String graceOnPrincipalPayment, List<HashMap> tranches, List<HashMap> collaterals) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal("10000.00") //
@@ -370,7 +403,7 @@ public class LoanReschedulingWithinCenterTest {
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withCharges(charges)//
.withCollaterals(collaterals).withCharges(charges)//
.build(clientID.toString(), groupId.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -23,8 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
@@ -205,13 +209,31 @@ public class LoanWithWaiveInterestAndWriteOffIntegrationTest {
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(PRINCIPAL)
.withLoanTermFrequency(LOAN_TERM_FREQUENCY).withLoanTermFrequencyAsMonths().withNumberOfRepayments(NUMBER_OF_REPAYMENTS)
.withRepaymentEveryAfter(REPAYMENT_PERIOD).withRepaymentFrequencyTypeAsMonths()
.withInterestRatePerPeriod(RATE_OF_INTEREST_PER_PERIOD).withInterestTypeAsFlatBalance()
.withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
.withExpectedDisbursementDate(EXPECTED_DISBURSAL_DATE).withSubmittedOnDate(LOAN_APPLICATION_SUBMISSION_DATE)
.build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
}
@@ -23,13 +23,18 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -65,11 +70,30 @@ public class LoanWithdrawnByApplicantIntegrationTest {
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplication = new LoanApplicationTestBuilder().withPrincipal("5000").withLoanTermFrequency("5")
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1")
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012")
.withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).withSubmittedOnDate("02 April 2012")
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplication);
}
}
@@ -25,10 +25,13 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.CalendarHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -83,12 +86,20 @@ public class MinimumDaysBetweenDisbursalAndFirstRepaymentTest {
final String disbursalDate = "04 September 2014";
final String firstRepaymentDate = "11 September 2014";
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
this.clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsWeeks().withNumberOfRepayments(numberOfRepayments)
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments()
.withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod)
.withRepaymentFrequencyTypeAsWeeks().withSubmittedOnDate(disbursalDate).withExpectedDisbursementDate(disbursalDate)
.withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate)
.withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate).withCollaterals(collaterals)
.build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -110,6 +121,17 @@ public class MinimumDaysBetweenDisbursalAndFirstRepaymentTest {
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
/*
* MinimumDaysBetweenDisbursalAndFirstRepayment is set to 7 days and days between disbursal date and first repayment
* is set as 7. system should allow to create this loan and allow to disburse
@@ -133,12 +155,20 @@ public class MinimumDaysBetweenDisbursalAndFirstRepaymentTest {
final String disbursalDate = "04 September 2014";
final String firstRepaymentDate = "05 September 2014";
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
this.clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsWeeks().withNumberOfRepayments(numberOfRepayments)
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments()
.withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod)
.withRepaymentFrequencyTypeAsWeeks().withSubmittedOnDate(disbursalDate).withExpectedDisbursementDate(disbursalDate)
.withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate)
.withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate).withCollaterals(collaterals)
.build(this.clientId.toString(), this.loanProductId.toString(), null);
List<HashMap> error = (List<HashMap>) this.loanTransactionHelper.createLoanAccount(loanApplicationJSON,
@@ -23,8 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.GroupHelper;
import org.apache.fineract.integrationtests.common.NotesHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -186,13 +190,33 @@ public class NotesTest {
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplication = new LoanApplicationTestBuilder().withPrincipal("5000").withLoanTermFrequency("5")
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1")
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012")
.withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).withSubmittedOnDate("02 April 2012")
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplication);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
private HashMap<String, String> collaterals(Integer collateralId, BigDecimal quantity) {
HashMap<String, String> collateral = new HashMap<String, String>(2);
collateral.put("clientCollateralId", collateralId.toString());
collateral.put("quantity", quantity.toString());
return collateral;
}
@Test
public void testUpdateLoanNote() {
String noteText = "this is a test loan note";

Some files were not shown because too many files have changed in this diff Show More