Merge pull request #1148 from pramodn02/develop

MIFOSX-1675 : Added support to capture guarantor funding details for loan account
This commit is contained in:
Vishwas Babu A J
2014-11-24 19:17:56 +05:30
37 changed files with 1167 additions and 199 deletions
@@ -198,10 +198,11 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder deleteGuarantor(final Long loanId, final Long guarantorId) {
public CommandWrapperBuilder deleteGuarantor(final Long loanId, final Long guarantorId, final Long guarantorFundingId) {
this.actionName = "DELETE";
this.entityName = "GUARANTOR";
this.entityId = guarantorId;
this.subentityId = guarantorFundingId;
this.loanId = loanId;
this.href = "/loans/" + loanId + "/guarantors/" + guarantorId;
return this;
@@ -55,6 +55,16 @@ public class ApiParameterHelper {
return fields;
}
public static void excludeAssociationsForResponseIfProvided(final MultivaluedMap<String, String> queryParams, Set<String> fields) {
String commaSerperatedParameters = "";
if (queryParams.getFirst("exclude") != null) {
commaSerperatedParameters = queryParams.getFirst("exclude");
if (StringUtils.isNotBlank(commaSerperatedParameters)) {
fields.removeAll(new HashSet<>(Arrays.asList(commaSerperatedParameters.split("\\s*,\\s*"))));
}
}
}
public static boolean prettyPrint(final MultivaluedMap<String, String> queryParams) {
boolean prettyPrint = false;
if (queryParams.getFirst("pretty") != null) {
@@ -0,0 +1,70 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.data;
public class PortfolioAccountDTO {
private final Integer accountTypeId;
private final Long clientId;
private final String currencyCode;
private final long[] accountStatus;
private final Integer depositType;
private final boolean excludeOverDraftAccounts;
public PortfolioAccountDTO(final Integer accountTypeId, final Long clientId, final String currencyCode, final long[] accountStatus,
final Integer depositType, final boolean excludeOverDraftAccounts) {
this.accountTypeId = accountTypeId;
this.clientId = clientId;
this.currencyCode = currencyCode;
this.accountStatus = accountStatus;
this.depositType = depositType;
this.excludeOverDraftAccounts = excludeOverDraftAccounts;
}
public PortfolioAccountDTO(final Integer accountTypeId, final Long clientId, final long[] accountStatus) {
this.accountTypeId = accountTypeId;
this.clientId = clientId;
this.currencyCode = null;
this.accountStatus = accountStatus;
this.depositType = null;
this.excludeOverDraftAccounts = false;
}
public PortfolioAccountDTO(final Integer accountTypeId, final Long clientId, final String currencyCode, final long[] accountStatus,
final Integer depositType) {
this.accountTypeId = accountTypeId;
this.clientId = clientId;
this.currencyCode = currencyCode;
this.accountStatus = accountStatus;
this.depositType = depositType;
this.excludeOverDraftAccounts = false;
}
public Integer getAccountTypeId() {
return this.accountTypeId;
}
public Long getClientId() {
return this.clientId;
}
public String getCurrencyCode() {
return this.currencyCode;
}
public long[] getAccountStatus() {
return this.accountStatus;
}
public Integer getDepositType() {
return this.depositType;
}
public boolean isExcludeOverDraftAccounts() {
return this.excludeOverDraftAccounts;
}
}
@@ -42,25 +42,30 @@ public class AccountAssociations extends AbstractPersistable<Long> {
@Column(name = "association_type_enum", nullable = false)
private Integer associationType;
@SuppressWarnings("unused")
@Column(name = "is_active", nullable = false)
private boolean active = true;
protected AccountAssociations() {}
private AccountAssociations(final Loan loanAccount, final SavingsAccount savingsAccount, final Loan linkedLoanAccount,
final SavingsAccount linkedSavingsAccount, final Integer associationType) {
final SavingsAccount linkedSavingsAccount, final Integer associationType, boolean active) {
this.loanAccount = loanAccount;
this.savingsAccount = savingsAccount;
this.linkedLoanAccount = linkedLoanAccount;
this.linkedSavingsAccount = linkedSavingsAccount;
this.associationType = associationType;
this.active = active;
}
public static AccountAssociations associateSavingsAccount(final Loan loan, final SavingsAccount savingsAccount,
final Integer associationType) {
return new AccountAssociations(loan, null, null, savingsAccount, associationType);
final Integer associationType, boolean isActive) {
return new AccountAssociations(loan, null, null, savingsAccount, associationType, isActive);
}
public static AccountAssociations associateSavingsAccount(final SavingsAccount savingsAccount,
final SavingsAccount linkedSavingsAccount, final Integer associationType) {
return new AccountAssociations(null, savingsAccount, null, linkedSavingsAccount, associationType);
final SavingsAccount linkedSavingsAccount, final Integer associationType, boolean isActive) {
return new AccountAssociations(null, savingsAccount, null, linkedSavingsAccount, associationType, isActive);
}
public SavingsAccount linkedSavingsAccount() {
@@ -9,6 +9,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
@@ -85,28 +86,38 @@ public class AccountAssociationsReadPlatformServiceImpl implements AccountAssoci
@Override
public boolean isLinkedWithAnyActiveAccount(final Long savingsId) {
boolean hasActiveAccount = false;
final String sql = "select loanAccount.loan_status_id as status from m_portfolio_account_associations aa "
+ "left join m_loan loanAccount on loanAccount.id = aa.loan_account_id " + "where aa.linked_savings_account_id = ?";
final List<Integer> statusList = this.jdbcTemplate.queryForList(sql, Integer.class, savingsId);
for (final Integer status : statusList) {
if (status != null) {
final LoanStatus loanStatus = LoanStatus.fromInt(status);
if (loanStatus.isActiveOrAwaitingApprovalOrDisbursal() || loanStatus.isUnderTransfer()) { return true; }
}
}
final String savsql = "select savingAccount.status_enum as status from m_portfolio_account_associations aa "
final String sql1 = "select aa.is_active as active,aa.association_type_enum as type, loanAccount.loan_status_id as loanStatus,"
+ "savingAccount.status_enum as savingsStatus from m_portfolio_account_associations aa "
+ "left join m_loan loanAccount on loanAccount.id = aa.loan_account_id "
+ "left join m_savings_account savingAccount on savingAccount.id = aa.savings_account_id "
+ "where aa.linked_savings_account_id = ?";
final List<Integer> savstatusList = this.jdbcTemplate.queryForList(savsql, Integer.class, savingsId);
for (final Integer status : savstatusList) {
if (status != null) {
final SavingsAccountStatusType saveStatus = SavingsAccountStatusType.fromInt(status);
if (saveStatus.isActiveOrAwaitingApprovalOrDisbursal() || saveStatus.isUnderTransfer()) { return true; }
final List<Map<String, Object>> statusList = this.jdbcTemplate.queryForList(sql1, savingsId);
for (final Map<String, Object> statusMap : statusList) {
AccountAssociationType associationType = AccountAssociationType.fromInt((Integer) statusMap.get("type"));
if (!associationType.isLinkedAccountAssociation() && (Boolean) statusMap.get("active")) {
hasActiveAccount = true;
break;
}
if (statusMap.get("loanStatus") != null) {
final LoanStatus loanStatus = LoanStatus.fromInt((Integer) statusMap.get("loanStatus"));
if (loanStatus.isActiveOrAwaitingApprovalOrDisbursal() || loanStatus.isUnderTransfer()) {
hasActiveAccount = true;
break;
}
}
if (statusMap.get("savingsStatus") != null) {
final SavingsAccountStatusType saveStatus = SavingsAccountStatusType.fromInt((Integer) statusMap.get("savingsStatus"));
if (saveStatus.isActiveOrAwaitingApprovalOrDisbursal() || saveStatus.isUnderTransfer()) {
hasActiveAccount = true;
break;
}
}
}
return hasActiveAccount;
}
@@ -25,6 +25,7 @@ import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.AccountTransferData;
import org.mifosplatform.portfolio.account.data.PortfolioAccountDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.exception.AccountTransferNotFoundException;
@@ -124,8 +125,9 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
if (mostRelevantFromAccountType == 1) {
loanStatus = new long[] { 300, 700 };
}
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(mostRelevantFromAccountType,
mostRelevantFromClientId, loanStatus);
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
loanStatus);
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
}
Collection<OfficeData> fromOfficeOptions = null;
@@ -178,8 +180,9 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null, null);
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(toAccountType, toClientId, currencyCode, null, null);
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService
.retrieveAllForLookup(portfolioAccountDTO);
if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions);
} else {
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.account.service;
import java.util.Collection;
import org.mifosplatform.portfolio.account.data.PortfolioAccountDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
public interface PortfolioAccountReadPlatformService {
@@ -15,7 +16,5 @@ public interface PortfolioAccountReadPlatformService {
PortfolioAccountData retrieveOne(Long accountId, Integer accountTypeId, String currencyCode);
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId, long[] accountStatus);
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId, String currencyCode, long[] accountStatus, Integer depositType);
Collection<PortfolioAccountData> retrieveAllForLookup(final PortfolioAccountDTO portfolioAccountDTO);
}
@@ -16,6 +16,7 @@ import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.PortfolioAccountDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.exception.AccountTransferNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
@@ -86,36 +87,29 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount
}
@Override
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId,
final long[] accountStatus) {
return retrieveAllForLookup(accountTypeId, clientId, null, accountStatus, null);
}
@Override
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId,
final String currencyCode, final long[] accountStatus, final Integer depositType) {
public Collection<PortfolioAccountData> retrieveAllForLookup(final PortfolioAccountDTO portfolioAccountDTO) {
List<Object> sqlParams = new ArrayList<>();
sqlParams.add(clientId);
sqlParams.add(portfolioAccountDTO.getClientId());
Collection<PortfolioAccountData> accounts = null;
String sql = null;
String defaultAccountStatus = "300";
if (accountStatus != null) {
for (final long status : accountStatus) {
if (portfolioAccountDTO.getAccountStatus() != null) {
for (final long status : portfolioAccountDTO.getAccountStatus()) {
defaultAccountStatus += ", " + status;
}
defaultAccountStatus = defaultAccountStatus.substring(defaultAccountStatus.indexOf(",") + 1);
}
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId);
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(portfolioAccountDTO.getAccountTypeId());
switch (accountType) {
case INVALID:
break;
case LOAN:
sql = "select " + this.loanAccountMapper.schema() + " where la.client_id = ? and la.loan_status_id in ("
+ defaultAccountStatus.toString() + ")";
if (currencyCode != null) {
if (portfolioAccountDTO.getCurrencyCode() != null) {
sql += " and la.currency_code = ?";
sqlParams.add(currencyCode);
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
}
accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams.toArray());
@@ -123,14 +117,18 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount
case SAVINGS:
sql = "select " + this.savingsAccountMapper.schema() + " where sa.client_id = ? and sa.status_enum in ("
+ defaultAccountStatus.toString() + ")";
if (currencyCode != null) {
if (portfolioAccountDTO.getCurrencyCode() != null) {
sql += " and sa.currency_code = ?";
sqlParams.add(currencyCode);
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
}
if (depositType != null) {
if (portfolioAccountDTO.getDepositType() != null) {
sql += " and sa.deposit_type_enum = ?";
sqlParams.add(depositType);
sqlParams.add(portfolioAccountDTO.getDepositType());
}
if(portfolioAccountDTO.isExcludeOverDraftAccounts()){
sql += " and sa.allow_overdraft = 0";
}
accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams.toArray());
@@ -31,6 +31,7 @@ import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.PortfolioAccountDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.data.StandingInstructionDTO;
import org.mifosplatform.portfolio.account.data.StandingInstructionData;
@@ -152,8 +153,9 @@ public class StandingInstructionReadPlatformServiceImpl implements StandingInstr
if (mostRelevantFromAccountType == 1) {
loanStatus = new long[] { 300, 700 };
}
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(mostRelevantFromAccountType,
mostRelevantFromClientId, loanStatus);
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
loanStatus);
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
}
Collection<OfficeData> fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
@@ -228,8 +230,9 @@ public class StandingInstructionReadPlatformServiceImpl implements StandingInstr
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null, null);
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(toAccountType, toClientId, currencyCode, null, null);
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService
.retrieveAllForLookup(portfolioAccountDTO);
if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions);
} else {
@@ -46,6 +46,7 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.PortfolioAccountDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.service.AccountAssociationsReadPlatformService;
import org.mifosplatform.portfolio.account.service.PortfolioAccountReadPlatformService;
@@ -306,9 +307,9 @@ public class LoansApiResource {
currencyCode = currencyData.code();
}
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(
PortfolioAccountType.SAVINGS.getValue(), clientId, currencyCode, accountStatus,
DepositAccountType.SAVINGS_DEPOSIT.getValue());
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(), clientId,
currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue());
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
}
@@ -362,6 +363,8 @@ public class LoansApiResource {
"charges", "guarantors", "collateral", "notes", "linkedAccount", "multiDisburseDetails"));
}
ApiParameterHelper.excludeAssociationsForResponseIfProvided(uriInfo.getQueryParameters(), associationParameters);
if (associationParameters.contains("guarantors")) {
mandatoryResponseParameters.add("guarantors");
guarantors = this.guarantorReadPlatformService.retrieveGuarantorsForLoan(loanId);
@@ -491,8 +494,9 @@ public class LoansApiResource {
currencyCode = currencyData.code();
}
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(PortfolioAccountType.SAVINGS.getValue(),
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(),
loanBasicDetails.clientId(), currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue());
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
if (!associationParameters.contains("linkedAccount")) {
mandatoryResponseParameters.add("linkedAccount");
@@ -19,7 +19,7 @@ public class GuarantorConstants {
LOAN_ID("loanId"), CLIENT_RELATIONSHIP_TYPE_ID("clientRelationshipTypeId"), GUARANTOR_TYPE_ID("guarantorTypeId"), ENTITY_ID(
"entityId"), FIRSTNAME("firstname"), LASTNAME("lastname"), ADDRESS_LINE_1("addressLine1"), ADDRESS_LINE_2("addressLine2"), CITY(
"city"), STATE("state"), ZIP("zip"), COUNTRY("country"), MOBILE_NUMBER("mobileNumber"), PHONE_NUMBER("housePhoneNumber"), COMMENT(
"comment"), DATE_OF_BIRTH("dob");
"comment"), DATE_OF_BIRTH("dob"), AMOUNT("amount"), SAVINGS_ID("savingsId");
private final String value;
@@ -19,6 +19,7 @@ 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;
@@ -34,11 +35,17 @@ import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants;
import org.mifosplatform.portfolio.account.data.PortfolioAccountDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.service.PortfolioAccountReadPlatformService;
import org.mifosplatform.portfolio.loanaccount.guarantor.GuarantorConstants;
import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorType;
import org.mifosplatform.portfolio.loanaccount.guarantor.service.GuarantorEnumerations;
import org.mifosplatform.portfolio.loanaccount.guarantor.service.GuarantorReadPlatformService;
import org.mifosplatform.portfolio.loanaccount.service.LoanReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -61,18 +68,24 @@ public class GuarantorsApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
private final LoanReadPlatformService loanReadPlatformService;
@Autowired
public GuarantorsApiResource(final PlatformSecurityContext context, final GuarantorReadPlatformService guarantorReadPlatformService,
final DefaultToApiJsonSerializer<GuarantorData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final CodeValueReadPlatformService codeValueReadPlatformService) {
final CodeValueReadPlatformService codeValueReadPlatformService,
final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService,
final LoanReadPlatformService loanReadPlatformService) {
this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.apiJsonSerializerService = toApiJsonSerializer;
this.guarantorReadPlatformService = guarantorReadPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
this.loanReadPlatformService = loanReadPlatformService;
}
@GET
@@ -85,7 +98,9 @@ public class GuarantorsApiResource {
final List<EnumOptionData> guarantorTypeOptions = GuarantorEnumerations.guarantorType(GuarantorType.values());
final Collection<CodeValueData> allowedClientRelationshipTypes = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(GuarantorConstants.GUARANTOR_RELATIONSHIP_CODE_NAME);
final GuarantorData guarantorData = GuarantorData.template(guarantorTypeOptions, allowedClientRelationshipTypes);
final Collection<PortfolioAccountData> accountLinkingOptions = null;
final GuarantorData guarantorData = GuarantorData.template(guarantorTypeOptions, allowedClientRelationshipTypes,
accountLinkingOptions);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serialize(settings, guarantorData, RESPONSE_DATA_PARAMETERS);
@@ -119,7 +134,9 @@ public class GuarantorsApiResource {
final Collection<CodeValueData> allowedClientRelationshipTypes = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(GuarantorConstants.GUARANTOR_RELATIONSHIP_CODE_NAME);
final List<EnumOptionData> guarantorTypeOptions = GuarantorEnumerations.guarantorType(GuarantorType.values());
guarantorData = GuarantorData.templateOnTop(guarantorData, guarantorTypeOptions, allowedClientRelationshipTypes);
final Collection<PortfolioAccountData> accountLinkingOptions = null;
guarantorData = GuarantorData.templateOnTop(guarantorData, guarantorTypeOptions, allowedClientRelationshipTypes,
accountLinkingOptions);
}
return this.apiJsonSerializerService.serialize(settings, guarantorData, RESPONSE_DATA_PARAMETERS);
@@ -155,11 +172,31 @@ public class GuarantorsApiResource {
@Path("{guarantorId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGuarantor(@PathParam("loanId") final Long loanId, @PathParam("guarantorId") final Long guarantorId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGuarantor(loanId, guarantorId).build();
public String deleteGuarantor(@PathParam("loanId") final Long loanId, @PathParam("guarantorId") final Long guarantorId,
@QueryParam("guarantorFundingId") final Long guarantorFundingId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGuarantor(loanId, guarantorId, guarantorFundingId).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
@GET
@Path("accounts/template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String accountsTemplate(@QueryParam("clientId") final Long clientId, @PathParam("loanId") final Long loanId,
@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(), clientId, null);
Collection<PortfolioAccountData> accountLinkingOptions = null;
if (this.loanReadPlatformService.isGuaranteeRequired(loanId)) {
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
}
final GuarantorData guarantorData = GuarantorData.template(null, null, accountLinkingOptions);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serialize(settings, guarantorData, AccountTransfersApiConstants.RESPONSE_DATA_PARAMETERS);
}
}
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.command;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -41,11 +42,13 @@ public class GuarantorCommand {
private final String housePhoneNumber;
private final String comment;
private final LocalDate dob;
private final Long savingsId;
private final BigDecimal amount;
public GuarantorCommand(final Long clientRelationshipTypeId, final Integer guarantorTypeId, final Long entityId,
final String firstname, final String lastname, final String addressLine1, final String addressLine2, final String city,
final String state, final String zip, final String country, final String mobileNumber, final String housePhoneNumber,
final String comment, final LocalDate dob) {
final String comment, final LocalDate dob, final Long savingsId, final BigDecimal amount) {
this.clientRelationshipTypeId = clientRelationshipTypeId;
@@ -66,6 +69,8 @@ public class GuarantorCommand {
this.housePhoneNumber = housePhoneNumber;
this.comment = comment;
this.dob = dob;
this.savingsId = savingsId;
this.amount = amount;
}
public boolean isExternalGuarantor() {
@@ -92,6 +97,12 @@ public class GuarantorCommand {
if (!isExternalGuarantor()) {
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.ENTITY_ID.getValue()).value(this.entityId).notNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.SAVINGS_ID.getValue()).value(this.savingsId)
.longGreaterThanZero();
if (this.savingsId != null) {
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.AMOUNT.getValue()).value(this.amount).notNull()
.positiveAmount();
}
} else {
// validate for an external guarantor
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.FIRSTNAME.getValue()).value(this.firstname).notBlank()
@@ -120,6 +131,12 @@ public class GuarantorCommand {
if (!isExternalGuarantor()) {
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.ENTITY_ID.getValue()).value(this.entityId).ignoreIfNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.SAVINGS_ID.getValue()).value(this.savingsId)
.longGreaterThanZero();
if (this.savingsId != null) {
baseDataValidator.reset().parameter(GUARANTOR_JSON_INPUT_PARAMS.AMOUNT.getValue()).value(this.amount).notNull()
.positiveAmount();
}
} else {
// TODO: Vishwas this validation is buggy (it is compulsory to
// update
@@ -185,4 +202,12 @@ public class GuarantorCommand {
public Integer getGuarantorTypeId() {
return this.guarantorTypeId;
}
public Long getSavingsId() {
return this.savingsId;
}
public BigDecimal getAmount() {
return this.amount;
}
}
@@ -12,6 +12,7 @@ import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorType;
import org.mifosplatform.portfolio.loanaccount.guarantor.service.GuarantorEnumerations;
@@ -44,48 +45,56 @@ public class GuarantorData {
private final String housePhoneNumber;
private final String comment;
private final LocalDate dob;
private final Collection<GuarantorFundingData> guarantorFundingDetails;
private final boolean status;
// template
@SuppressWarnings("unused")
private final List<EnumOptionData> guarantorTypeOptions;
private final Collection<CodeValueData> allowedClientRelationshipTypes;
private final Collection<PortfolioAccountData> accountLinkingOptions;
public static GuarantorData template(final List<EnumOptionData> guarantorTypeOptions,
final Collection<CodeValueData> allowedClientRelationshipTypes) {
final Collection<CodeValueData> allowedClientRelationshipTypes, Collection<PortfolioAccountData> accountLinkingOptions) {
final Collection<GuarantorFundingData> guarantorFundingDetails = null;
final boolean status = false;
return new GuarantorData(null, null, null, null, GuarantorEnumerations.guarantorType(GuarantorType.CUSTOMER), null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, guarantorTypeOptions,
allowedClientRelationshipTypes);
null, null, null, null, null, null, null, null, null, null, null, null, status, guarantorFundingDetails,
guarantorTypeOptions, allowedClientRelationshipTypes, accountLinkingOptions);
}
public static GuarantorData templateOnTop(final GuarantorData guarantorData, final List<EnumOptionData> guarantorTypeOptions,
final Collection<CodeValueData> allowedClientRelationshipTypes) {
final Collection<CodeValueData> allowedClientRelationshipTypes, Collection<PortfolioAccountData> accountLinkingOptions) {
return new GuarantorData(guarantorData.id, guarantorData.loanId, guarantorData.clientRelationshipType, guarantorData.entityId,
guarantorData.guarantorType, guarantorData.firstname, guarantorData.lastname, guarantorData.dob,
guarantorData.addressLine1, guarantorData.addressLine2, guarantorData.city, guarantorData.state, guarantorData.zip,
guarantorData.country, guarantorData.mobileNumber, guarantorData.housePhoneNumber, guarantorData.comment,
guarantorData.officeName, guarantorData.joinedDate, guarantorData.externalId, guarantorTypeOptions,
allowedClientRelationshipTypes);
guarantorData.officeName, guarantorData.joinedDate, guarantorData.externalId, guarantorData.status,
guarantorData.guarantorFundingDetails, guarantorTypeOptions, allowedClientRelationshipTypes, accountLinkingOptions);
}
public static GuarantorData mergeClientData(final ClientData clientData, final GuarantorData guarantorData) {
return new GuarantorData(guarantorData.id, guarantorData.loanId, guarantorData.clientRelationshipType, guarantorData.entityId,
guarantorData.guarantorType, clientData.getFirstname(), clientData.getLastname(), null, null, null, null, null, null, null,
null, null, null, clientData.officeName(), clientData.getActivationDate(), clientData.getExternalId(), null,
guarantorData.allowedClientRelationshipTypes);
null, null, null, clientData.officeName(), clientData.getActivationDate(), clientData.getExternalId(),
guarantorData.status, guarantorData.guarantorFundingDetails, null, guarantorData.allowedClientRelationshipTypes,
guarantorData.accountLinkingOptions);
}
public static GuarantorData mergeStaffData(final StaffData staffData, final GuarantorData guarantorData) {
return new GuarantorData(guarantorData.id, guarantorData.loanId, guarantorData.clientRelationshipType, guarantorData.entityId,
guarantorData.guarantorType, staffData.getFirstname(), staffData.getLastname(), null, null, null, null, null, null, null,
null, null, null, staffData.getOfficeName(), null, null, null, guarantorData.allowedClientRelationshipTypes);
null, null, null, staffData.getOfficeName(), null, null, guarantorData.status, guarantorData.guarantorFundingDetails, null,
guarantorData.allowedClientRelationshipTypes, guarantorData.accountLinkingOptions);
}
public GuarantorData(final Long id, final Long loanId, final CodeValueData clientRelationshipType, final Long entityId,
final EnumOptionData guarantorType, final String firstname, final String lastname, final LocalDate dob,
final String addressLine1, final String addressLine2, final String city, final String state, final String zip,
final String country, final String mobileNumber, final String housePhoneNumber, final String comment, final String officeName,
final LocalDate joinedDate, final String externalId, final List<EnumOptionData> guarantorTypeOptions,
final Collection<CodeValueData> allowedClientRelationshipTypes) {
final LocalDate joinedDate, final String externalId, final boolean status,
Collection<GuarantorFundingData> guarantorFundingDetails, final List<EnumOptionData> guarantorTypeOptions,
final Collection<CodeValueData> allowedClientRelationshipTypes, final Collection<PortfolioAccountData> accountLinkingOptions) {
this.id = id;
this.loanId = loanId;
this.clientRelationshipType = clientRelationshipType;
@@ -106,8 +115,11 @@ public class GuarantorData {
this.officeName = officeName;
this.joinedDate = joinedDate;
this.externalId = externalId;
this.status = status;
this.guarantorFundingDetails = guarantorFundingDetails;
this.guarantorTypeOptions = guarantorTypeOptions;
this.allowedClientRelationshipTypes = allowedClientRelationshipTypes;
this.accountLinkingOptions = accountLinkingOptions;
}
public boolean isExternalGuarantor() {
@@ -0,0 +1,52 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.data;
import java.math.BigDecimal;
import java.util.Collection;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
public class GuarantorFundingData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final EnumOptionData status;
@SuppressWarnings("unused")
private final PortfolioAccountData savingsAccount;
@SuppressWarnings("unused")
private final BigDecimal amount;
@SuppressWarnings("unused")
private final BigDecimal amountReleased;
@SuppressWarnings("unused")
private final BigDecimal amountRemaining;
@SuppressWarnings("unused")
private final BigDecimal amountTransfered;
@SuppressWarnings("unused")
private final Collection<GuarantorTransactionData> guarantorTransactions;
private GuarantorFundingData(final Long id, final EnumOptionData status, final PortfolioAccountData savingsAccount, final BigDecimal amount,
final BigDecimal amountReleased, final BigDecimal amountRemaining, final BigDecimal amountTransfered,
final Collection<GuarantorTransactionData> guarantorTransactions) {
this.id = id;
this.status = status;
this.savingsAccount = savingsAccount;
this.amount = amount;
this.amountReleased = amountReleased;
this.amountRemaining = amountRemaining;
this.amountTransfered = amountTransfered;
this.guarantorTransactions = guarantorTransactions;
}
public static GuarantorFundingData instance(final Long id, final EnumOptionData status, final PortfolioAccountData savingsAccount, final BigDecimal amount,
final BigDecimal amountReleased, final BigDecimal amountRemaining, final BigDecimal amountTransfered,
final Collection<GuarantorTransactionData> guarantorTransactions) {
return new GuarantorFundingData(id, status, savingsAccount, amount, amountReleased, amountRemaining, amountTransfered,
guarantorTransactions);
}
}
@@ -0,0 +1,36 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.data;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData;
import org.mifosplatform.portfolio.savings.data.DepositAccountOnHoldTransactionData;
public class GuarantorTransactionData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final DepositAccountOnHoldTransactionData onHoldTransactionData;
@SuppressWarnings("unused")
private final LoanTransactionData loanTransactionData;
@SuppressWarnings("unused")
private final boolean reversed;
private GuarantorTransactionData(final Long id, final DepositAccountOnHoldTransactionData onHoldTransactionData,
final LoanTransactionData loanTransactionData, final boolean reversed) {
this.id = id;
this.onHoldTransactionData = onHoldTransactionData;
this.loanTransactionData = loanTransactionData;
this.reversed = reversed;
}
public static GuarantorTransactionData instance(final Long id, final DepositAccountOnHoldTransactionData onHoldTransactionData,
final LoanTransactionData loanTransactionData, final boolean reversed) {
return new GuarantorTransactionData(id, onHoldTransactionData, loanTransactionData, reversed);
}
}
@@ -5,19 +5,25 @@
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.domain;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
@@ -79,22 +85,22 @@ public class Guarantor extends AbstractPersistable<Long> {
@Column(name = "comment", length = 500)
private String comment;
@Column(name = "is_active", nullable = false)
private boolean active;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "guarantor", orphanRemoval = true)
private final List<GuarantorFundingDetails> guarantorFundDetails = new ArrayList<>();
protected Guarantor() {
}
public static Guarantor createNew(final Loan loan, final CodeValue clientRelationshipType, final Integer gurantorType,
final Long entityId, final String firstname, final String lastname, final Date dateOfBirth, final String addressLine1,
final String addressLine2, final String city, final String state, final String country, final String zip,
final String housePhoneNumber, final String mobilePhoneNumber, final String comment) {
return new Guarantor(loan, clientRelationshipType, gurantorType, entityId, firstname, lastname, dateOfBirth, addressLine1,
addressLine2, city, state, country, zip, housePhoneNumber, mobilePhoneNumber, comment);
}
public Guarantor(final Loan loan, final CodeValue clientRelationshipType, final Integer gurantorType, final Long entityId,
private Guarantor(final Loan loan, final CodeValue clientRelationshipType, final Integer gurantorType, final Long entityId,
final String firstname, final String lastname, final Date dateOfBirth, final String addressLine1, final String addressLine2,
final String city, final String state, final String country, final String zip, final String housePhoneNumber,
final String mobilePhoneNumber, final String comment) {
final String mobilePhoneNumber, final String comment, final boolean active,
final List<GuarantorFundingDetails> guarantorFundDetails) {
this.loan = loan;
this.clientRelationshipType = clientRelationshipType;
this.gurantorType = gurantorType;
@@ -111,13 +117,16 @@ public class Guarantor extends AbstractPersistable<Long> {
this.housePhoneNumber = StringUtils.defaultIfEmpty(housePhoneNumber, null);
this.mobilePhoneNumber = StringUtils.defaultIfEmpty(mobilePhoneNumber, null);
this.comment = StringUtils.defaultIfEmpty(comment, null);
this.active = active;
this.guarantorFundDetails.addAll(guarantorFundDetails);
}
public static Guarantor fromJson(final Loan loan, final CodeValue clientRelationshipType, final JsonCommand command) {
public static Guarantor fromJson(final Loan loan, final CodeValue clientRelationshipType, final JsonCommand command,
final List<GuarantorFundingDetails> fundingDetails) {
final Integer gurantorType = command.integerValueSansLocaleOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.GUARANTOR_TYPE_ID
.getValue());
final Long entityId = command.longValueOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.ENTITY_ID.getValue());
final boolean active = true;
if (GuarantorType.EXTERNAL.getValue().equals(gurantorType)) {
final String firstname = command.stringValueOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.FIRSTNAME.getValue());
final String lastname = command.stringValueOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.LASTNAME.getValue());
@@ -133,11 +142,11 @@ public class Guarantor extends AbstractPersistable<Long> {
final String comment = command.stringValueOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.COMMENT.getValue());
return new Guarantor(loan, clientRelationshipType, gurantorType, entityId, firstname, lastname, dateOfBirth, addressLine1,
addressLine2, city, state, country, zip, housePhoneNumber, mobilePhoneNumber, comment);
addressLine2, city, state, country, zip, housePhoneNumber, mobilePhoneNumber, comment, active, fundingDetails);
}
return new Guarantor(loan, clientRelationshipType, gurantorType, entityId, null, null, null, null, null, null, null, null, null,
null, null, null);
null, null, null, active, fundingDetails);
}
@@ -145,7 +154,6 @@ public class Guarantor extends AbstractPersistable<Long> {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
handlePropertyUpdate(command, actualChanges, GUARANTOR_JSON_INPUT_PARAMS.GUARANTOR_TYPE_ID.getValue(), this.gurantorType, true);
handlePropertyUpdate(command, actualChanges, GUARANTOR_JSON_INPUT_PARAMS.CLIENT_RELATIONSHIP_TYPE_ID.getValue(), 0, true);
if (isExternalGuarantor()) {
@@ -162,9 +170,6 @@ public class Guarantor extends AbstractPersistable<Long> {
handlePropertyUpdate(command, actualChanges, GUARANTOR_JSON_INPUT_PARAMS.MOBILE_NUMBER.getValue(), this.mobilePhoneNumber);
handlePropertyUpdate(command, actualChanges, GUARANTOR_JSON_INPUT_PARAMS.COMMENT.getValue(), this.comment);
updateExistingEntityToNull();
} else {
handlePropertyUpdate(command, actualChanges, GUARANTOR_JSON_INPUT_PARAMS.ENTITY_ID.getValue(), this.entityId);
updateExternalGuarantorFieldsToNull();
}
return actualChanges;
@@ -235,20 +240,6 @@ public class Guarantor extends AbstractPersistable<Long> {
}
}
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
Long propertyToBeUpdated) {
if (command.isChangeInLongParameterNamed(paramName, propertyToBeUpdated)) {
final Long newValue = command.longValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
propertyToBeUpdated = newValue;
// now update actual property
if (paramName.equals(GUARANTOR_JSON_INPUT_PARAMS.ENTITY_ID.getValue())) {
this.entityId = newValue;
}
}
}
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
Date propertyToBeUpdated) {
if (command.isChangeInDateParameterNamed(paramName, propertyToBeUpdated)) {
@@ -287,21 +278,6 @@ public class Guarantor extends AbstractPersistable<Long> {
this.clientRelationshipType = clientRelationshipType;
}
private void updateExternalGuarantorFieldsToNull() {
this.firstname = null;
this.lastname = null;
this.dateOfBirth = null;
this.addressLine1 = null;
this.addressLine2 = null;
this.city = null;
this.state = null;
this.country = null;
this.zip = null;
this.housePhoneNumber = null;
this.mobilePhoneNumber = null;
this.comment = null;
}
private void updateExistingEntityToNull() {
this.entityId = null;
}
@@ -309,4 +285,64 @@ public class Guarantor extends AbstractPersistable<Long> {
public Integer getGurantorType() {
return this.gurantorType;
}
public boolean isActive() {
return this.active;
}
public void updateStatus(final boolean status) {
this.active = status;
}
public void addFundingDetails(final List<GuarantorFundingDetails> fundingDetails) {
this.guarantorFundDetails.addAll(fundingDetails);
}
public void updateStatus(final GuarantorFundingDetails guarantorFundingDetails, final GuarantorFundStatusType fundStatusType) {
guarantorFundingDetails.updateStatus(fundStatusType);
updateStatus();
}
public GuarantorFundingDetails getGuarantorFundingDetail(final Long fundingDetailId) {
GuarantorFundingDetails guarantorFundingDetails = null;
for (GuarantorFundingDetails fundingDetails : this.guarantorFundDetails) {
if (fundingDetails.getId().equals(fundingDetailId)) {
guarantorFundingDetails = fundingDetails;
break;
}
}
return guarantorFundingDetails;
}
private void updateStatus() {
boolean isActive = false;
for (GuarantorFundingDetails guarantorFundingDetails : this.guarantorFundDetails) {
if (guarantorFundingDetails.getStatus().isActive()) {
isActive = true;
break;
}
}
this.active = isActive;
}
public Loan getLoan() {
return this.loan;
}
public List<GuarantorFundingDetails> getGuarantorFundDetails() {
return this.guarantorFundDetails;
}
public boolean hasGuarantor(Long savingsId) {
if (savingsId == null) { return false; }
boolean hasGuarantee = false;
for (GuarantorFundingDetails guarantorFundingDetails : this.guarantorFundDetails) {
if (guarantorFundingDetails.getStatus().isActive()
&& savingsId.equals(guarantorFundingDetails.getLinkedSavingsAccount().getId())) {
hasGuarantee = true;
break;
}
}
return hasGuarantee;
}
}
@@ -0,0 +1,78 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.domain;
/**
* Enum representation of {@link Guarantor} status states.
*/
public enum GuarantorFundStatusType {
INVALID(0, "guarantorFundStatusType.invalid"), //
ACTIVE(100, "guarantorFundStatusType.active"), //
COMPLETED(200, "guarantorFundStatusType.completed"), //
WITHDRAWN(300, "guarantorFundStatusType.withdrawn"), //
DELETED(400, "guarantorFundStatusType.deleted");
private final Integer value;
private final String code;
public static GuarantorFundStatusType fromInt(final Integer type) {
GuarantorFundStatusType enumeration = GuarantorFundStatusType.INVALID;
switch (type) {
case 100:
enumeration = GuarantorFundStatusType.ACTIVE;
break;
case 200:
enumeration = GuarantorFundStatusType.COMPLETED;
break;
case 300:
enumeration = GuarantorFundStatusType.WITHDRAWN;
break;
case 400:
enumeration = GuarantorFundStatusType.DELETED;
break;
}
return enumeration;
}
private GuarantorFundStatusType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final GuarantorFundStatusType state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isActive() {
return this.value.equals(GuarantorFundStatusType.ACTIVE.getValue());
}
public boolean isClosed() {
return isWithdrawn() || isCompleted() || isDeleted();
}
public boolean isWithdrawn() {
return this.value.equals(GuarantorFundStatusType.WITHDRAWN.getValue());
}
public boolean isCompleted() {
return this.value.equals(GuarantorFundStatusType.COMPLETED.getValue());
}
public boolean isDeleted() {
return this.value.equals(GuarantorFundStatusType.DELETED.getValue());
}
}
@@ -0,0 +1,81 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.domain;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.mifosplatform.portfolio.account.domain.AccountAssociations;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_guarantor_funding_details")
public class GuarantorFundingDetails extends AbstractPersistable<Long> {
@ManyToOne
@JoinColumn(name = "guarantor_id", nullable = false)
private Guarantor guarantor;
@ManyToOne
@JoinColumn(name = "account_associations_id", nullable = false)
private AccountAssociations accountAssociations;
@Column(name = "status_enum", nullable = false)
private Integer status;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@Column(name = "amount_released_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal amountReleased;
@Column(name = "amount_remaining_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal amountRemaining;
@Column(name = "amount_transfered_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal amountTransfered;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "guarantorFundingDetails", orphanRemoval = true)
private final List<GuarantorFundingTransaction> guarantorFundingTransactions = new ArrayList<>();
protected GuarantorFundingDetails() {}
public GuarantorFundingDetails(final AccountAssociations accountAssociations, final Integer status, final BigDecimal amount) {
this.accountAssociations = accountAssociations;
this.status = status;
this.amount = amount;
this.amountRemaining = amount;
}
public void updateGuarantor(final Guarantor guarantor) {
this.guarantor = guarantor;
}
public void updateStatus(final GuarantorFundStatusType guarantorFundStatusType) {
this.status = guarantorFundStatusType.getValue();
}
public GuarantorFundStatusType getStatus(){
return GuarantorFundStatusType.fromInt(this.status);
}
public SavingsAccount getLinkedSavingsAccount(){
return accountAssociations.linkedSavingsAccount();
}
}
@@ -0,0 +1,37 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.savings.domain.DepositAccountOnHoldTransaction;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_guarantor_transaction")
public class GuarantorFundingTransaction extends AbstractPersistable<Long> {
@ManyToOne
@JoinColumn(name = "guarantor_fund_detail_id", nullable = false)
private GuarantorFundingDetails guarantorFundingDetails;
@ManyToOne
@JoinColumn(name = "loan_transaction_id", nullable = false)
private LoanTransaction loanTransaction;
@ManyToOne
@JoinColumn(name = "deposit_on_hold_transaction_id", nullable = false)
private DepositAccountOnHoldTransaction depositAccountOnHoldTransaction;
@Column(name = "is_reversed", nullable = false)
private boolean reversed;
}
@@ -13,11 +13,16 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN
public class GuarantorNotFoundException extends AbstractPlatformResourceNotFoundException {
public GuarantorNotFoundException(final Long id) {
super("error.msg.loan.guarantor.", "Guarantor with identifier " + id + " does not exist", id);
super("error.msg.loan.guarantor.not.found", "Guarantor with identifier " + id + " does not exist", id);
}
public GuarantorNotFoundException(final Long loanId, final Long guarantorId) {
super("error.msg.loan.guarantor.", "Guarantor with identifier " + guarantorId + " does not exist for loan with Identifier "
+ loanId, loanId, guarantorId);
super("error.msg.loan.guarantor.not.found", "Guarantor with identifier " + guarantorId
+ " does not exist for loan with Identifier " + loanId, loanId, guarantorId);
}
public GuarantorNotFoundException(final Long loanId, final Long guarantorId, final Long guarantorFundingId) {
super("error.msg.loan.guarantor.not.found", "Guarantor with identifier " + guarantorId + "and with funding detail "
+ guarantorFundingId + " does not exist for loan with Identifier " + loanId, loanId, guarantorId, guarantorFundingId);
}
}
@@ -17,5 +17,10 @@ public class InvalidGuarantorException extends AbstractPlatformDomainRuleExcepti
super("error.msg.invalid.guarantor", "Tried to set Client with id " + clientId
+ " as a guarantor to his/her own loan with loan identifier =" + loanId, clientId, loanId);
}
public InvalidGuarantorException(final Long clientId, final Long loanId,final String errorcode) {
super("error.msg."+errorcode, "Tried to set Client with id " + clientId
+ " as a guarantor to his/her own loan with loan identifier =" + loanId, clientId, loanId);
}
}
@@ -26,6 +26,6 @@ public class DeleteGuarantorCommandHandler implements NewCommandSourceHandler {
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.guarantorWritePlatformService.removeGuarantor(command.getLoanId(), command.entityId());
return this.guarantorWritePlatformService.removeGuarantor(command.getLoanId(), command.entityId(), command.subentityId());
}
}
@@ -6,6 +6,8 @@
package org.mifosplatform.portfolio.loanaccount.guarantor.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -48,7 +50,13 @@ public final class GuarantorCommandFromApiJsonDeserializer extends AbstractFromA
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(element.getAsJsonObject());
return extractGuarantorCommand(element, locale, dateFormat);
}
private GuarantorCommand extractGuarantorCommand(final JsonElement element, final Locale locale, final String dateFormat) {
final Long clientRelationshipTypeId = this.fromApiJsonHelper.extractLongNamed(
GUARANTOR_JSON_INPUT_PARAMS.CLIENT_RELATIONSHIP_TYPE_ID.getValue(), element);
final Integer guarantorTypeId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
@@ -69,9 +77,14 @@ public final class GuarantorCommandFromApiJsonDeserializer extends AbstractFromA
final String housePhoneNumber = this.fromApiJsonHelper.extractStringNamed(GUARANTOR_JSON_INPUT_PARAMS.PHONE_NUMBER.getValue(),
element);
final String comment = this.fromApiJsonHelper.extractStringNamed(GUARANTOR_JSON_INPUT_PARAMS.COMMENT.getValue(), element);
final LocalDate dob = this.fromApiJsonHelper.extractLocalDateNamed(GUARANTOR_JSON_INPUT_PARAMS.DATE_OF_BIRTH.getValue(), element);
final LocalDate dob = this.fromApiJsonHelper.extractLocalDateNamed(GUARANTOR_JSON_INPUT_PARAMS.DATE_OF_BIRTH.getValue(), element,
dateFormat, locale);
final Long savingsId = this.fromApiJsonHelper.extractLongNamed(GUARANTOR_JSON_INPUT_PARAMS.SAVINGS_ID.getValue(), element);
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalNamed(GUARANTOR_JSON_INPUT_PARAMS.AMOUNT.getValue(), element,
locale);
return new GuarantorCommand(clientRelationshipTypeId, guarantorTypeId, entityId, firstname, lastname, addressLine1, addressLine2,
city, state, zip, country, mobileNumber, housePhoneNumber, comment, dob);
city, state, zip, country, mobileNumber, housePhoneNumber, comment, dob, savingsId, amount);
}
}
@@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundStatusType;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorType;
public class GuarantorEnumerations {
@@ -31,4 +32,14 @@ public class GuarantorEnumerations {
return optionDatas;
}
public static EnumOptionData guarantorFundStatusType(final int id) {
return guarantorFundStatusType(GuarantorFundStatusType.fromInt(id));
}
public static EnumOptionData guarantorFundStatusType(final GuarantorFundStatusType guarantorFundType) {
final EnumOptionData optionData = new EnumOptionData(guarantorFundType.getValue().longValue(), guarantorFundType.getCode(),
guarantorFundType.toString());
return optionData;
}
}
@@ -5,9 +5,11 @@
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate;
@@ -17,12 +19,18 @@ import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.domain.AccountAssociationType;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException;
import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorFundingData;
import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorTransactionData;
import org.mifosplatform.portfolio.savings.data.DepositAccountOnHoldTransactionData;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
@@ -45,20 +53,69 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe
this.loanRepository = loanRepository;
}
@Override
public List<GuarantorData> retrieveGuarantorsForValidLoan(final Long loanId) {
final Loan loan = this.loanRepository.findOne(loanId);
if (loan == null) { throw new LoanNotFoundException(loanId); }
return retrieveGuarantorsForLoan(loanId);
}
@Override
public List<GuarantorData> retrieveGuarantorsForLoan(final Long loanId) {
final GuarantorMapper rm = new GuarantorMapper();
String sql = "select " + rm.schema();
sql += " where loan_id = ? group by g.id,gfd.id";
final List<GuarantorData> guarantorDatas = this.jdbcTemplate.query(sql, rm,
new Object[] { AccountAssociationType.GUARANTOR_ACCOUNT_ASSOCIATION.getValue(),
loanId });
final List<GuarantorData> mergedGuarantorDatas = new ArrayList<>();
for (final GuarantorData guarantorData : guarantorDatas) {
mergedGuarantorDatas.add(mergeDetailsForClientOrStaffGuarantor(guarantorData));
}
return mergedGuarantorDatas;
}
@Override
public GuarantorData retrieveGuarantor(final Long loanId, final Long guarantorId) {
final GuarantorMapper rm = new GuarantorMapper();
String sql = "select " + rm.schema();
sql += " where g.loan_id = ? and g.id = ? group by g.id,gfd.id";
final GuarantorData guarantorData = this.jdbcTemplate.queryForObject(sql, rm,
new Object[] { AccountAssociationType.GUARANTOR_ACCOUNT_ASSOCIATION.getValue(),
loanId, guarantorId });
return mergeDetailsForClientOrStaffGuarantor(guarantorData);
}
private static final class GuarantorMapper implements RowMapper<GuarantorData> {
private GuarantorTransactionMapper guarantorTransactionMapper = new GuarantorTransactionMapper();
private GuarantorFundingMapper guarantorFundingMapper = new GuarantorFundingMapper(guarantorTransactionMapper);
private final StringBuilder sqlBuilder = new StringBuilder(
" g.id as id, g.loan_id as loanId, g.client_reln_cv_id clientRelationshipTypeId, g.entity_id as entityId, g.type_enum guarantorType ,g.firstname as firstname, g.lastname as lastname, g.dob as dateOfBirth, g.address_line_1 as addressLine1, g.address_line_2 as addressLine2, g.city as city, g.state as state, g.country as country, g.zip as zip, g.house_phone_number as housePhoneNumber, g.mobile_number as mobilePhoneNumber, g.comment as comment, ")
.append(" cv.code_value as typeName")//
.append(" g.is_active as guarantorStatus,")//
.append(" cv.code_value as typeName, ")//
.append("gfd.amount,")//
.append(this.guarantorFundingMapper.schema())//
.append(",")//
.append(this.guarantorTransactionMapper.schema())//
.append(" FROM m_guarantor g") //
.append(" left JOIN m_code_value cv on g.client_reln_cv_id = cv.id");
.append(" left JOIN m_code_value cv on g.client_reln_cv_id = cv.id")//
.append(" left JOIN m_guarantor_funding_details gfd on g.id = gfd.guarantor_id")//
.append(" left JOIN m_portfolio_account_associations aa on gfd.account_associations_id = aa.id and aa.is_active = 1 and aa.association_type_enum = ?")//
.append(" left JOIN m_savings_account sa on sa.id = aa.linked_savings_account_id ")//
.append(" left join m_guarantor_transaction gt on gt.guarantor_fund_detail_id = gfd.id") //
.append(" left join m_deposit_account_on_hold_transaction oht on oht.id = gt.deposit_on_hold_transaction_id");
public String schema() {
return this.sqlBuilder.toString();
}
@Override
public GuarantorData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
public GuarantorData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long loanId = rs.getLong("loanId");
final Long clientRelationshipTypeId = JdbcSupport.getLong(rs, "clientRelationshipTypeId");
@@ -84,41 +141,127 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe
final String mobileNumber = rs.getString("mobilePhoneNumber");
final String housePhoneNumber = rs.getString("housePhoneNumber");
final String comment = rs.getString("comment");
final boolean status = rs.getBoolean("guarantorStatus");
final Collection<PortfolioAccountData> accountLinkingOptions = null;
List<GuarantorFundingData> guarantorFundingDetails = null;
GuarantorFundingData guarantorFundingData = this.guarantorFundingMapper.mapRow(rs, rowNum);
if (guarantorFundingData != null) {
guarantorFundingDetails = new ArrayList<>();
guarantorFundingDetails.add(guarantorFundingData);
while (rs.next()) {
Long tempId = rs.getLong("id");
if (tempId.equals(id)) {
guarantorFundingData = this.guarantorFundingMapper.mapRow(rs, rowNum);
guarantorFundingDetails.add(guarantorFundingData);
} else {
rs.previous();
break;
}
}
}
return new GuarantorData(id, loanId, clientRelationshipType, entityId, guarantorType, firstname, lastname, dob, addressLine1,
addressLine2, city, state, zip, country, mobileNumber, housePhoneNumber, comment, null, null, null, null, null);
addressLine2, city, state, zip, country, mobileNumber, housePhoneNumber, comment, null, null, null, status,
guarantorFundingDetails, null, null, accountLinkingOptions);
}
}
@Override
public List<GuarantorData> retrieveGuarantorsForValidLoan(final Long loanId) {
final Loan loan = this.loanRepository.findOne(loanId);
if (loan == null) { throw new LoanNotFoundException(loanId); }
return retrieveGuarantorsForLoan(loanId);
}
private static final class GuarantorFundingMapper implements RowMapper<GuarantorFundingData> {
@Override
public List<GuarantorData> retrieveGuarantorsForLoan(final Long loanId) {
final GuarantorMapper rm = new GuarantorMapper();
String sql = "select " + rm.schema();
sql += " where loan_id = ?";
final List<GuarantorData> guarantorDatas = this.jdbcTemplate.query(sql, rm, new Object[] { loanId });
private final String sql;
private final GuarantorTransactionMapper guarantorTransactionMapper;
final List<GuarantorData> mergedGuarantorDatas = new ArrayList<>();
public GuarantorFundingMapper(final GuarantorTransactionMapper guarantorTransactionMapper) {
this.guarantorTransactionMapper = guarantorTransactionMapper;
StringBuilder sb = new StringBuilder(" gfd.id as gfdId,");
sb.append(" gfd.amount as amount, gfd.amount_released_derived as amountReleased, ");
sb.append(" gfd.amount_remaining_derived as amountRemaining, ");
sb.append(" gfd.amount_transfered_derived as amountTransfered, gfd.status_enum as statusEnum, ");
sb.append(" sa.id as savingsId, sa.account_no as accountNumber ");
sql = sb.toString();
}
for (final GuarantorData guarantorData : guarantorDatas) {
mergedGuarantorDatas.add(mergeDetailsForClientOrStaffGuarantor(guarantorData));
public String schema() {
return this.sql;
}
@Override
public GuarantorFundingData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
GuarantorFundingData guarantorFundingData = null;
final Long id = rs.getLong("gfdId");
if (id != null && id > 0) {
final BigDecimal amount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amount");
final BigDecimal amountReleased = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountReleased");
final BigDecimal amountRemaining = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountRemaining");
final BigDecimal amountTransfered = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountTransfered");
final int statusEnum = rs.getInt("statusEnum");
final EnumOptionData status = GuarantorEnumerations.guarantorFundStatusType(statusEnum);
final Long savingsId = rs.getLong("savingsId");
final String savingsAccountNumber = rs.getString("accountNumber");
final PortfolioAccountData portfolioAccountData = PortfolioAccountData.lookup(savingsId, savingsAccountNumber);
List<GuarantorTransactionData> guarantorTransactions = new ArrayList<>();
if (this.guarantorTransactionMapper != null) {
GuarantorTransactionData guarantorTransactionData = this.guarantorTransactionMapper.mapRow(rs, rowNum);
if (guarantorTransactionData != null) {
guarantorTransactions.add(guarantorTransactionData);
while (rs.next()) {
final Long tempFundId = rs.getLong("gfdId");
if (tempFundId != null && tempFundId.equals(id)) {
guarantorTransactionData = this.guarantorTransactionMapper.mapRow(rs, rowNum);
guarantorTransactions.add(guarantorTransactionData);
} else {
rs.previous();
break;
}
}
}
}
guarantorFundingData = GuarantorFundingData.instance(id, status, portfolioAccountData, amount, amountReleased,
amountRemaining, amountTransfered, guarantorTransactions);
}
return guarantorFundingData;
}
return mergedGuarantorDatas;
}
@Override
public GuarantorData retrieveGuarantor(final Long loanId, final Long guarantorId) {
final GuarantorMapper rm = new GuarantorMapper();
String sql = "select " + rm.schema();
sql += " where g.loan_id = ? and g.id = ?";
final GuarantorData guarantorData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { loanId, guarantorId });
private static final class GuarantorTransactionMapper implements RowMapper<GuarantorTransactionData> {
private final String sql;
public GuarantorTransactionMapper() {
StringBuilder sb = new StringBuilder(" gt.id as gtId,");
sb.append("gt.is_reversed as reversed,");
sb.append(" oht.id as ohtId, oht.amount as transactionAmount, ");
sb.append(" oht.transaction_type_enum as transactionType, ");
sb.append(" oht.transaction_date as transactionDate, oht.is_reversed as transactionReversed ");
sql = sb.toString();
}
public String schema() {
return this.sql;
}
@Override
public GuarantorTransactionData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
GuarantorTransactionData guarantorTransactionData = null;
final Long id = rs.getLong("gtId");
final Long transactionId = rs.getLong("ohtId");
final BigDecimal amount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transactionAmount");
final LocalDate date = JdbcSupport.getLocalDate(rs, "transactionDate");
final int transactionTypeEnum = rs.getInt("transactionType");
EnumOptionData transactionType = SavingsEnumerations.onHoldTransactionType(transactionTypeEnum);
final boolean reversed = rs.getBoolean("reversed");
final boolean transactionReversed = rs.getBoolean("transactionReversed");
if (id != null) {
DepositAccountOnHoldTransactionData onHoldTransactionData = DepositAccountOnHoldTransactionData.instance(transactionId,
amount, transactionType, date, transactionReversed);
guarantorTransactionData = GuarantorTransactionData.instance(id, onHoldTransactionData, null, reversed);
}
return guarantorTransactionData;
}
return mergeDetailsForClientOrStaffGuarantor(guarantorData);
}
/**
@@ -14,6 +14,6 @@ public interface GuarantorWritePlatformService {
CommandProcessingResult updateGuarantor(final Long loanId, final Long guarantorId, final JsonCommand command);
CommandProcessingResult removeGuarantor(final Long loanId, final Long guarantorId);
CommandProcessingResult removeGuarantor(final Long loanId, final Long guarantorId, Long guarantorFundingId);
}
@@ -5,6 +5,8 @@
*/
package org.mifosplatform.portfolio.loanaccount.guarantor.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -15,6 +17,9 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.account.domain.AccountAssociationType;
import org.mifosplatform.portfolio.account.domain.AccountAssociations;
import org.mifosplatform.portfolio.account.domain.AccountAssociationsRepository;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepositoryWrapper;
@@ -22,12 +27,16 @@ import org.mifosplatform.portfolio.loanaccount.guarantor.GuarantorConstants;
import org.mifosplatform.portfolio.loanaccount.guarantor.GuarantorConstants.GUARANTOR_JSON_INPUT_PARAMS;
import org.mifosplatform.portfolio.loanaccount.guarantor.command.GuarantorCommand;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.Guarantor;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundStatusType;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingDetails;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorRepository;
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorType;
import org.mifosplatform.portfolio.loanaccount.guarantor.exception.DuplicateGuarantorException;
import org.mifosplatform.portfolio.loanaccount.guarantor.exception.GuarantorNotFoundException;
import org.mifosplatform.portfolio.loanaccount.guarantor.exception.InvalidGuarantorException;
import org.mifosplatform.portfolio.loanaccount.guarantor.serialization.GuarantorCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -46,28 +55,49 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
private final GuarantorRepository guarantorRepository;
private final GuarantorCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
private final SavingsAccountAssembler savingsAccountAssembler;
private final AccountAssociationsRepository accountAssociationsRepository;
@Autowired
public GuarantorWritePlatformServiceJpaRepositoryIImpl(final LoanRepositoryWrapper loanRepositoryWrapper,
final GuarantorRepository guarantorRepository, final ClientRepositoryWrapper clientRepositoryWrapper,
final StaffRepositoryWrapper staffRepositoryWrapper, final GuarantorCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final CodeValueRepositoryWrapper codeValueRepositoryWrapper) {
final CodeValueRepositoryWrapper codeValueRepositoryWrapper, final SavingsAccountAssembler savingsAccountAssembler,
final AccountAssociationsRepository accountAssociationsRepository) {
this.loanRepositoryWrapper = loanRepositoryWrapper;
this.clientRepositoryWrapper = clientRepositoryWrapper;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.guarantorRepository = guarantorRepository;
this.staffRepositoryWrapper = staffRepositoryWrapper;
this.codeValueRepositoryWrapper = codeValueRepositoryWrapper;
this.savingsAccountAssembler = savingsAccountAssembler;
this.accountAssociationsRepository = accountAssociationsRepository;
}
@Override
@Transactional
public CommandProcessingResult createGuarantor(final Long loanId, final JsonCommand command) {
try {
final GuarantorCommand guarantorCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
guarantorCommand.validateForCreate();
final GuarantorCommand guarantorCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
return createGuarantor(loan, command, guarantorCommand, existGuarantorList);
}
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
private CommandProcessingResult createGuarantor(final Loan loan, final JsonCommand command, final GuarantorCommand guarantorCommand,
final Collection<Guarantor> existGuarantorList) {
try {
guarantorCommand.validateForCreate();
final List<GuarantorFundingDetails> guarantorFundingDetails = new ArrayList<>();
AccountAssociations accountAssociations = null;
if (guarantorCommand.getSavingsId() != null) {
final SavingsAccount savingsAccount = this.savingsAccountAssembler.assembleFrom(guarantorCommand.getSavingsId());
accountAssociations = AccountAssociations.associateSavingsAccount(loan, savingsAccount,
AccountAssociationType.GUARANTOR_ACCOUNT_ASSOCIATION.getValue(), true);
GuarantorFundingDetails fundingDetails = new GuarantorFundingDetails(accountAssociations,
GuarantorFundStatusType.ACTIVE.getValue(), guarantorCommand.getAmount());
guarantorFundingDetails.add(fundingDetails);
}
final Long clientRelationshipId = guarantorCommand.getClientRelationshipTypeId();
CodeValue clientRelationshipType = null;
@@ -77,36 +107,47 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
GuarantorConstants.GUARANTOR_RELATIONSHIP_CODE_NAME, clientRelationshipId);
}
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
final Long entityId = guarantorCommand.getEntityId();
final Integer guarantorTypeId = guarantorCommand.getGuarantorTypeId();
Guarantor guarantor = null;
for (final Guarantor avilableGuarantor : existGuarantorList) {
if (entityId != null && avilableGuarantor.getEntityId() == entityId
&& avilableGuarantor.getGurantorType() == guarantorTypeId && avilableGuarantor.isActive()) {
if (guarantorCommand.getSavingsId() == null || avilableGuarantor.hasGuarantor(guarantorCommand.getSavingsId())) {
/** Get the right guarantor based on guarantorType **/
String defaultUserMessage = null;
if (guarantorTypeId == GuarantorType.STAFF.getValue()) {
defaultUserMessage = this.staffRepositoryWrapper.findOneWithNotFoundDetection(entityId).displayName();
} else {
defaultUserMessage = this.clientRepositoryWrapper.findOneWithNotFoundDetection(entityId).getDisplayName();
}
for (final Guarantor guarantor : existGuarantorList) {
if (guarantor.getLoanId() == loanId && entityId != null && guarantor.getEntityId() == entityId
&& guarantor.getGurantorType() == guarantorTypeId) {
/** Get the right guarantor based on guarantorType **/
String defaultUserMessage = null;
if (guarantorTypeId == GuarantorType.STAFF.getValue()) {
defaultUserMessage = this.staffRepositoryWrapper.findOneWithNotFoundDetection(entityId).displayName();
} else {
defaultUserMessage = this.clientRepositoryWrapper.findOneWithNotFoundDetection(entityId).getDisplayName();
defaultUserMessage = defaultUserMessage + " is already exist as a guarantor for this loan";
final String action = loan.client() != null ? "client.guarantor" : "group.guarantor";
throw new DuplicateGuarantorException(action, "is.already.exist.same.loan", defaultUserMessage, entityId,
loan.getId());
}
defaultUserMessage = defaultUserMessage + " is already exist as a guarantor for this loan";
final String action = loan.client() != null ? "client.guarantor" : "group.guarantor";
throw new DuplicateGuarantorException(action, "is.already.exist.same.loan", defaultUserMessage, entityId, loanId);
guarantor = avilableGuarantor;
break;
}
}
Guarantor guarantor = null;
guarantor = Guarantor.fromJson(loan, clientRelationshipType, command);
if (guarantor == null) {
guarantor = Guarantor.fromJson(loan, clientRelationshipType, command, guarantorFundingDetails);
} else {
guarantor.addFundingDetails(guarantorFundingDetails);
}
validateGuarantorBusinessRules(guarantor);
for (GuarantorFundingDetails fundingDetails : guarantorFundingDetails) {
fundingDetails.updateGuarantor(guarantor);
}
this.guarantorRepository.saveAndFlush(guarantor);
if (accountAssociations != null) {
this.accountAssociationsRepository.save(accountAssociations);
}
this.guarantorRepository.save(guarantor);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantor.getOfficeId())
.withEntityId(guarantor.getId()).withLoanId(loanId).build();
.withEntityId(guarantor.getId()).withLoanId(loan.getId()).build();
} catch (final DataIntegrityViolationException dve) {
handleGuarantorDataIntegrityIssues(dve);
return CommandProcessingResult.empty();
@@ -142,8 +183,8 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
if (guarantorType.isCustomer() || guarantorType.isStaff()) {
final Long entityId = guarantorCommand.getEntityId();
for (final Guarantor guarantor : existGuarantorList) {
if (guarantor.getLoanId() == loanId && guarantor.getEntityId() == entityId
&& guarantor.getGurantorType() == guarantorTypeId && !guarantorForUpdate.getId().equals(guarantor.getId())) {
if (guarantor.getEntityId() == entityId && guarantor.getGurantorType() == guarantorTypeId
&& !guarantorForUpdate.getId().equals(guarantor.getId())) {
String defaultUserMessage = this.clientRepositoryWrapper.findOneWithNotFoundDetection(entityId).getDisplayName();
defaultUserMessage = defaultUserMessage + " is already exist as a guarantor for this loan";
final String action = loan.client() != null ? "client.guarantor" : "group.guarantor";
@@ -158,7 +199,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
}
if (!changesOnly.isEmpty()) {
this.guarantorRepository.saveAndFlush(guarantorForUpdate);
this.guarantorRepository.save(guarantorForUpdate);
}
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantorForUpdate.getOfficeId())
@@ -171,29 +212,55 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
@Override
@Transactional
public CommandProcessingResult removeGuarantor(final Long loanId, final Long guarantorId) {
public CommandProcessingResult removeGuarantor(final Long loanId, final Long guarantorId, final Long guarantorFundingId) {
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
final Guarantor guarantorForDelete = this.guarantorRepository.findByLoanAndId(loan, guarantorId);
if (guarantorForDelete == null) { throw new GuarantorNotFoundException(loanId, guarantorId); }
this.guarantorRepository.delete(guarantorForDelete);
return new CommandProcessingResultBuilder().withEntityId(guarantorId).withLoanId(guarantorForDelete.getLoanId())
.withOfficeId(guarantorForDelete.getOfficeId()).build();
if (guarantorForDelete == null || (guarantorFundingId == null && !guarantorForDelete.getGuarantorFundDetails().isEmpty())) { throw new GuarantorNotFoundException(
loanId, guarantorId, guarantorFundingId); }
return removeGuarantor(guarantorForDelete, loanId, guarantorFundingId);
}
private CommandProcessingResult removeGuarantor(final Guarantor guarantorForDelete, final Long loanId, final Long guarantorFundingId) {
if (guarantorFundingId == null) {
guarantorForDelete.updateStatus(false);
} else {
GuarantorFundingDetails guarantorFundingDetails = guarantorForDelete.getGuarantorFundingDetail(guarantorFundingId);
if (guarantorFundingDetails == null) { throw new GuarantorNotFoundException(loanId, guarantorForDelete.getId(),
guarantorFundingId); }
GuarantorFundStatusType fundStatusType = GuarantorFundStatusType.DELETED;
if (guarantorForDelete.getLoan().isDisbursed()) {
fundStatusType = GuarantorFundStatusType.WITHDRAWN;
}
guarantorForDelete.updateStatus(guarantorFundingDetails, fundStatusType);
}
this.guarantorRepository.save(guarantorForDelete);
CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder()
.withEntityId(guarantorForDelete.getId()).withLoanId(guarantorForDelete.getLoanId())
.withOfficeId(guarantorForDelete.getOfficeId());
if (guarantorFundingId != null) {
commandProcessingResultBuilder.withSubEntityId(guarantorFundingId);
}
return commandProcessingResultBuilder.build();
}
private void validateGuarantorBusinessRules(final Guarantor guarantor) {
// validate guarantor conditions
if (guarantor.isExistingCustomer()) {
// check client exists
this.clientRepositoryWrapper.findOneWithNotFoundDetection(guarantor.getEntityId());
// validate that the client is not set as a self guarantor
if (guarantor.getClientId() != null) {
if (guarantor.getClientId().equals(guarantor.getEntityId())) {
//
throw new InvalidGuarantorException(guarantor.getEntityId(), guarantor.getLoanId());
if (guarantor.getClientId() != null && guarantor.getClientId().equals(guarantor.getEntityId())) {
String errorCode = null;
if (guarantor.getGuarantorFundDetails().isEmpty()) {
errorCode = "guarantor.can.not.be.own";
} else if (guarantor.getClientRelationshipType() != null) {
errorCode = "guarantor.relation.should.be.empty.for.own";
}
if (errorCode != null) { throw new InvalidGuarantorException(guarantor.getEntityId(), guarantor.getLoanId(), errorCode); }
}
} else if (guarantor.isExistingEmployee()) {
this.staffRepositoryWrapper.findOneWithNotFoundDetection(guarantor.getEntityId());
}
@@ -260,8 +260,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
if (savingsAccountId != null) {
final SavingsAccount savingsAccount = this.savingsAccountAssembler.assembleFrom(savingsAccountId);
this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, newLoanApplication);
boolean isActive = true;
final AccountAssociations accountAssociations = AccountAssociations.associateSavingsAccount(newLoanApplication,
savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue());
savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive);
this.accountAssociationsRepository.save(accountAssociations);
}
@@ -598,8 +599,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final SavingsAccount savingsAccount = this.savingsAccountAssembler.assembleFrom(savingsAccountId);
this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, existingLoanApplication);
if (accountAssociations == null) {
boolean isActive = true;
accountAssociations = AccountAssociations.associateSavingsAccount(existingLoanApplication, savingsAccount,
AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue());
AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive);
} else {
accountAssociations.updateLinkedSavingsAccount(savingsAccount);
}
@@ -99,4 +99,6 @@ public interface LoanReadPlatformService {
Collection<LoanTransactionData> retrieveWaiverLoanTransactions(Long loanId);
Collection<LoanSchedulePeriodData> fetchWaiverInterestRepaymentData(Long loanId);
boolean isGuaranteeRequired(Long loanId);
}
@@ -1664,6 +1664,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
}
}
@Override
public boolean isGuaranteeRequired(final Long loanId) {
final String sql = "select pl.hold_guarantee_funds from m_loan ml inner join m_product_loan pl on pl.id = ml.product_id where ml.id=?";
return this.jdbcTemplate.queryForObject(sql, Boolean.class, loanId);
}
private static final class LoanTransactionDerivedComponentMapper implements RowMapper<LoanTransactionData> {
public String schema() {
@@ -0,0 +1,61 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.savings;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
/**
* An enumeration of on hold transactions that can occur on a
* {@link SavingsAccount}.
*/
public enum DepositAccountOnHoldTransactionType {
INVALID(0, "deposutAccountOnHoldTransactionType.invalid"), //
HOLD(1, "deposutAccountOnHoldTransactionType.hold"), //
RELEASE(2, "deposutAccountOnHoldTransactionType.release");
private final Integer value;
private final String code;
private DepositAccountOnHoldTransactionType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public static DepositAccountOnHoldTransactionType fromInt(final Integer transactionType) {
if (transactionType == null) { return DepositAccountOnHoldTransactionType.INVALID; }
DepositAccountOnHoldTransactionType savingsAccountTransactionType = DepositAccountOnHoldTransactionType.INVALID;
switch (transactionType) {
case 1:
savingsAccountTransactionType = DepositAccountOnHoldTransactionType.HOLD;
break;
case 2:
savingsAccountTransactionType = DepositAccountOnHoldTransactionType.RELEASE;
break;
}
return savingsAccountTransactionType;
}
public boolean isHold() {
return this.value.equals(DepositAccountOnHoldTransactionType.HOLD.getValue());
}
public boolean isRelease() {
return this.value.equals(DepositAccountOnHoldTransactionType.RELEASE.getValue());
}
}
@@ -0,0 +1,39 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.savings.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
public class DepositAccountOnHoldTransactionData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final BigDecimal amount;
@SuppressWarnings("unused")
private EnumOptionData transactionType;
@SuppressWarnings("unused")
private final LocalDate transactionDate;
@SuppressWarnings("unused")
private final boolean reversed;
private DepositAccountOnHoldTransactionData(final Long id, final BigDecimal amount, final EnumOptionData transactionType,
final LocalDate transactionDate, final boolean reversed) {
this.id = id;
this.amount = amount;
this.transactionType = transactionType;
this.transactionDate = transactionDate;
this.reversed = reversed;
}
public static DepositAccountOnHoldTransactionData instance(final Long id, final BigDecimal amount,
final EnumOptionData transactionType, final LocalDate transactionDate, final boolean reversed) {
return new DepositAccountOnHoldTransactionData(id, amount, transactionType, transactionDate, reversed);
}
}
@@ -0,0 +1,43 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.savings.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_deposit_account_on_hold_transaction")
public class DepositAccountOnHoldTransaction extends AbstractPersistable<Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "savings_account_id", nullable = true)
private SavingsAccount savingsAccount;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@Column(name = "transaction_type_enum", nullable = false)
private Integer transactionType;
@Temporal(TemporalType.DATE)
@Column(name = "transaction_date", nullable = false)
private Date transactionDate;
@Column(name = "is_reversed", nullable = false)
private boolean reversed;
}
@@ -200,8 +200,9 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(savingsAccountId,
DepositAccountType.SAVINGS_DEPOSIT);
this.depositAccountDataValidator.validatelinkedSavingsAccount(savingsAccount, account);
boolean isActive = true;
final AccountAssociations accountAssociations = AccountAssociations.associateSavingsAccount(account, savingsAccount,
AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue());
AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive);
this.accountAssociationsRepository.save(accountAssociations);
}
@@ -354,7 +355,7 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
this.savingAccountRepository.save(account);
}
boolean isLinkedAccRequired = command.booleanPrimitiveValueOfParameterNamed(transferInterestToSavingsParamName);
// Save linked account information
@@ -387,8 +388,9 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
DepositAccountType.SAVINGS_DEPOSIT);
this.depositAccountDataValidator.validatelinkedSavingsAccount(savingsAccount, account);
if (accountAssociations == null) {
boolean isActive = true;
accountAssociations = AccountAssociations.associateSavingsAccount(account, savingsAccount,
AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue());
AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive);
} else {
accountAssociations.updateLinkedSavingsAccount(savingsAccount);
}
@@ -464,7 +466,6 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.calendarInstanceRepository.save(calendarInstance);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(accountId) //
@@ -11,6 +11,7 @@ import java.util.List;
import org.mifosplatform.accounting.common.AccountingEnumerations;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.savings.DepositAccountOnClosureType;
import org.mifosplatform.portfolio.savings.DepositAccountOnHoldTransactionType;
import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.PreClosurePenalInterestOnType;
import org.mifosplatform.portfolio.savings.RecurringDepositType;
@@ -728,4 +729,28 @@ public class SavingsEnumerations {
}
return optionDatas;
}
public static EnumOptionData onHoldTransactionType(final int id) {
return onHoldTransactionType(DepositAccountOnHoldTransactionType.fromInt(id));
}
public static EnumOptionData onHoldTransactionType(final DepositAccountOnHoldTransactionType type) {
EnumOptionData optionData = new EnumOptionData(DepositAccountOnHoldTransactionType.INVALID.getValue().longValue(),
DepositAccountType.INVALID.getCode(), "Invalid");
switch (type) {
case INVALID:
break;
case HOLD:
optionData = new EnumOptionData(DepositAccountOnHoldTransactionType.HOLD.getValue().longValue(),
DepositAccountOnHoldTransactionType.HOLD.getCode(), "hold");
break;
case RELEASE:
optionData = new EnumOptionData(DepositAccountOnHoldTransactionType.RELEASE.getValue().longValue(),
DepositAccountOnHoldTransactionType.RELEASE.getCode(), "release");
break;
}
return optionData;
}
}
@@ -0,0 +1,47 @@
ALTER TABLE `m_portfolio_account_associations`
ADD COLUMN `is_active` TINYINT(1) NOT NULL DEFAULT '1';
ALTER TABLE `m_guarantor`
ADD COLUMN `is_active` TINYINT(1) NOT NULL DEFAULT '1';
CREATE TABLE `m_guarantor_funding_details` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`guarantor_id` BIGINT(20) NOT NULL,
`account_associations_id` BIGINT(20) NOT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`amount_released_derived` DECIMAL(19,6) NULL,
`amount_remaining_derived` DECIMAL(19,6) NULL,
`amount_transfered_derived` DECIMAL(19,6) NULL,
`status_enum` SMALLINT(3) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_m_guarantor_fund_details_m_guarantor` FOREIGN KEY (`guarantor_id`) REFERENCES `m_guarantor` (`id`),
CONSTRAINT `FK_m_guarantor_fund_details_account_associations_id` FOREIGN KEY (`account_associations_id`) REFERENCES `m_portfolio_account_associations` (`id`)
);
CREATE TABLE `m_deposit_account_on_hold_transaction` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`savings_account_id` BIGINT(20) NOT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`transaction_type_enum` SMALLINT(1) NOT NULL,
`transaction_date` DATE NOT NULL,
`is_reversed` TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
CONSTRAINT `FK_deposit_on_hold_transaction_m_savings_account` FOREIGN KEY (`savings_account_id`) REFERENCES `m_savings_account` (`id`)
);
CREATE TABLE `m_guarantor_transaction` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`guarantor_fund_detail_id` BIGINT(20) NOT NULL,
`loan_transaction_id` BIGINT(20) NOT NULL,
`deposit_on_hold_transaction_id` BIGINT(20) NOT NULL,
`is_reversed` TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
CONSTRAINT `FK_guarantor_transaction_m_deposit_account_on_hold_transaction` FOREIGN KEY (`deposit_on_hold_transaction_id`) REFERENCES `m_deposit_account_on_hold_transaction` (`id`),
CONSTRAINT `FK_guarantor_transaction_guarantor_fund_detail` FOREIGN KEY (`guarantor_fund_detail_id`) REFERENCES `m_guarantor_funding_details` (`id`),
CONSTRAINT `FK_guarantor_transaction_m_loan_transaction` FOREIGN KEY (`loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`)
);
ALTER TABLE `m_loan`
ADD COLUMN `guarantee_amount_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `interest_recalculation_enabled`,
ADD COLUMN `guarantee_outstanding_amount_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `guarantee_amount_derived`;