Merge pull request #1161 from pramodn02/develop
MIFOSX-1709 : guarantor on hold funds functionality
This commit is contained in:
@@ -290,6 +290,10 @@ public class CommandWrapper {
|
||||
return this.entityName.equalsIgnoreCase("GUARANTOR");
|
||||
}
|
||||
|
||||
public boolean isGuaranteeRecovery() {
|
||||
return this.actionName.equalsIgnoreCase("RECOVERGUARANTEES");
|
||||
}
|
||||
|
||||
public boolean isGLAccountResource() {
|
||||
return this.entityName.equalsIgnoreCase("GLACCOUNT");
|
||||
}
|
||||
|
||||
+10
-1
@@ -186,7 +186,16 @@ public class CommandWrapperBuilder {
|
||||
this.entityName = "GUARANTOR";
|
||||
this.entityId = null;
|
||||
this.loanId = loanId;
|
||||
this.href = "/loans/" + loanId + "/guarantors/template";
|
||||
this.href = "/loans/" + loanId + "/guarantors";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder recoverFromGuarantor(final Long loanId) {
|
||||
this.actionName = "RECOVERGUARANTEES";
|
||||
this.entityName = "LOAN";
|
||||
this.entityId = loanId;
|
||||
this.loanId = loanId;
|
||||
this.href = "/loans/" + loanId + "?command=recoverGuarantees";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -388,6 +388,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
handler = this.applicationContext.getBean("loanApplicationDeletionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUndoLoanWriteOff()) {
|
||||
handler = this.applicationContext.getBean("undoWriteOffLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isGuaranteeRecovery()) {
|
||||
handler = this.applicationContext.getBean("recoverFromGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
+7
-2
@@ -40,6 +40,7 @@ public class AccountTransferDTO {
|
||||
private final SavingsAccount toSavingsAccount;
|
||||
private final SavingsAccount fromSavingsAccount;
|
||||
private final Boolean isRegularTransaction;
|
||||
private final Boolean isExceptionForBalanceCheck;
|
||||
|
||||
public AccountTransferDTO(final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType, final Long fromAccountId,
|
||||
@@ -47,7 +48,7 @@ public class AccountTransferDTO {
|
||||
final PaymentDetail paymentDetail, final Integer fromTransferType, final Integer toTransferType, final Long chargeId,
|
||||
Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails,
|
||||
final String noteText, final String txnExternalId, final Loan loan, SavingsAccount toSavingsAccount,
|
||||
final SavingsAccount fromSavingsAccount,final Boolean isRegularTransaction) {
|
||||
final SavingsAccount fromSavingsAccount, final Boolean isRegularTransaction, Boolean isExceptionForBalanceCheck) {
|
||||
this.transactionDate = transactionDate;
|
||||
this.transactionAmount = transactionAmount;
|
||||
this.fromAccountType = fromAccountType;
|
||||
@@ -70,6 +71,7 @@ public class AccountTransferDTO {
|
||||
this.toSavingsAccount = toSavingsAccount;
|
||||
this.fromSavingsAccount = fromSavingsAccount;
|
||||
this.isRegularTransaction = isRegularTransaction;
|
||||
this.isExceptionForBalanceCheck = isExceptionForBalanceCheck;
|
||||
}
|
||||
|
||||
public LocalDate getTransactionDate() {
|
||||
@@ -156,9 +158,12 @@ public class AccountTransferDTO {
|
||||
return this.fromSavingsAccount;
|
||||
}
|
||||
|
||||
|
||||
public Boolean isRegularTransaction() {
|
||||
return this.isRegularTransaction;
|
||||
}
|
||||
|
||||
public Boolean isExceptionForBalanceCheck() {
|
||||
return this.isExceptionForBalanceCheck;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-5
@@ -240,7 +240,6 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
public Long transferFunds(final AccountTransferDTO accountTransferDTO) {
|
||||
Long transferTransactionId = null;
|
||||
final boolean isAccountTransfer = true;
|
||||
final boolean isWithdrawBalance = false;
|
||||
final boolean isRegularTransaction = accountTransferDTO.isRegularTransaction();
|
||||
AccountTransferDetails accountTransferDetails = accountTransferDTO.getAccountTransferDetails();
|
||||
if (isSavingsToLoanAccountTransfer(accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
|
||||
@@ -248,8 +247,19 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
SavingsAccount fromSavingsAccount = null;
|
||||
Loan toLoanAccount = null;
|
||||
if (accountTransferDetails == null) {
|
||||
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
|
||||
toLoanAccount = this.loanAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
|
||||
if (accountTransferDTO.getFromSavingsAccount() == null) {
|
||||
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
|
||||
} else {
|
||||
fromSavingsAccount = accountTransferDTO.getFromSavingsAccount();
|
||||
this.savingsAccountAssembler.setHelpers(fromSavingsAccount);
|
||||
}
|
||||
if (accountTransferDTO.getLoan() == null) {
|
||||
toLoanAccount = this.loanAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
|
||||
} else {
|
||||
toLoanAccount = accountTransferDTO.getLoan();
|
||||
this.loanAccountAssembler.setHelpers(toLoanAccount);
|
||||
}
|
||||
|
||||
} else {
|
||||
fromSavingsAccount = accountTransferDetails.fromSavingsAccount();
|
||||
this.savingsAccountAssembler.setHelpers(fromSavingsAccount);
|
||||
@@ -259,7 +269,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
|
||||
final SavingsTransactionBooleanValues transactionBooleanValues = new SavingsTransactionBooleanValues(isAccountTransfer,
|
||||
isRegularTransaction, fromSavingsAccount.isWithdrawalFeeApplicableForTransfer(), AccountTransferType.fromInt(
|
||||
accountTransferDTO.getTransferType()).isInterestTransfer(), isWithdrawBalance);
|
||||
accountTransferDTO.getTransferType()).isInterestTransfer(), accountTransferDTO.isExceptionForBalanceCheck());
|
||||
|
||||
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount,
|
||||
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
@@ -293,11 +303,13 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
|
||||
} else {
|
||||
fromSavingsAccount = accountTransferDTO.getFromSavingsAccount();
|
||||
this.savingsAccountAssembler.setHelpers(fromSavingsAccount);
|
||||
}
|
||||
if (accountTransferDTO.getToSavingsAccount() == null) {
|
||||
toSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
|
||||
} else {
|
||||
toSavingsAccount = accountTransferDTO.getToSavingsAccount();
|
||||
this.savingsAccountAssembler.setHelpers(toSavingsAccount);
|
||||
}
|
||||
} else {
|
||||
fromSavingsAccount = accountTransferDetails.fromSavingsAccount();
|
||||
@@ -308,7 +320,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
|
||||
final SavingsTransactionBooleanValues transactionBooleanValues = new SavingsTransactionBooleanValues(isAccountTransfer,
|
||||
isRegularTransaction, fromSavingsAccount.isWithdrawalFeeApplicableForTransfer(), AccountTransferType.fromInt(
|
||||
accountTransferDTO.getTransferType()).isInterestTransfer(), isWithdrawBalance);
|
||||
accountTransferDTO.getTransferType()).isInterestTransfer(), accountTransferDTO.isExceptionForBalanceCheck());
|
||||
|
||||
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount,
|
||||
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
@@ -332,6 +344,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
fromLoanAccount = this.loanAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
|
||||
} else {
|
||||
fromLoanAccount = accountTransferDTO.getLoan();
|
||||
this.loanAccountAssembler.setHelpers(fromLoanAccount);
|
||||
}
|
||||
toSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
|
||||
} else {
|
||||
|
||||
+2
-1
@@ -221,12 +221,13 @@ public class StandingInstructionWritePlatformServiceImpl implements StandingInst
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailRepository.findOne(data.accountDetailId());
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
accountTransferDetails.accountTransferStandingInstruction().updateLatsRunDate(transactionDate.toDate());
|
||||
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
|
||||
data.toAccountType(), data.fromAccount().accountId(), data.toAccount().accountId(), data.name()
|
||||
+ " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null, data
|
||||
.transferType().getValue(), accountTransferDetails, null, null, null, null, fromSavingsAccount,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferAmount(sb, accountTransferDTO, data.getId());
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -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.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class BusinessEventNotificationConstants {
|
||||
|
||||
public static enum BUSINESS_EVENTS {
|
||||
LOAN_APPROVED("loan_approved"), LOAN_UNDO_APPROVAL("loan_undo_approval"), LOAN_UNDO_DISBURSAL("loan_undo_disbursal"), LOAN_UNDO_TRANSACTION(
|
||||
"loan_undo_transaction"), LOAN_MAKE_REPAYMENT("loan_repayment_transaction"), LOAN_WRITTEN_OFF("loan_writtenoff"), LOAN_UNDO_WRITTEN_OFF(
|
||||
"loan_undo_writtenoff");
|
||||
|
||||
private final String value;
|
||||
|
||||
private BUSINESS_EVENTS(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
static {
|
||||
for (final BUSINESS_EVENTS type : BUSINESS_EVENTS.values()) {
|
||||
values.add(type.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 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.common.service;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
public interface BusinessEventListner {
|
||||
|
||||
public void businessEventToBeExecuted(AbstractPersistable<Long> businessEventEntity);
|
||||
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity);
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.common.service;
|
||||
|
||||
import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
public interface BusinessEventNotifierService {
|
||||
|
||||
public void notifyBusinessEventToBeExecuted(BUSINESS_EVENTS businessEvent, AbstractPersistable<Long> businessEventEntity);
|
||||
|
||||
public void notifyBusinessEventWasExecuted(BUSINESS_EVENTS businessEvent, AbstractPersistable<Long> businessEventEntity);
|
||||
|
||||
public void addBusinessEventPreListners(BUSINESS_EVENTS businessEvent, BusinessEventListner businessEventListner);
|
||||
|
||||
public void addBusinessEventPostListners(BUSINESS_EVENTS businessEvent, BusinessEventListner businessEventListner);
|
||||
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.common.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierService {
|
||||
|
||||
private final Map<BUSINESS_EVENTS, List<BusinessEventListner>> preListners = new HashMap<>(5);
|
||||
private final Map<BUSINESS_EVENTS, List<BusinessEventListner>> postListners = new HashMap<>(5);
|
||||
|
||||
@Override
|
||||
public void notifyBusinessEventToBeExecuted(BUSINESS_EVENTS businessEvent, AbstractPersistable<Long> businessEventEntity) {
|
||||
List<BusinessEventListner> businessEventListners = this.preListners.get(businessEvent);
|
||||
if (businessEventListners != null) {
|
||||
for (BusinessEventListner eventListner : businessEventListners) {
|
||||
eventListner.businessEventToBeExecuted(businessEventEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBusinessEventWasExecuted(BUSINESS_EVENTS businessEvent, AbstractPersistable<Long> businessEventEntity) {
|
||||
List<BusinessEventListner> businessEventListners = this.postListners.get(businessEvent);
|
||||
if (businessEventListners != null) {
|
||||
for (BusinessEventListner eventListner : businessEventListners) {
|
||||
eventListner.businessEventWasExecuted(businessEventEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBusinessEventPreListners(BUSINESS_EVENTS businessEvent, BusinessEventListner businessEventListner) {
|
||||
addBusinessEventListners(businessEvent, businessEventListner, preListners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBusinessEventPostListners(BUSINESS_EVENTS businessEvent, BusinessEventListner businessEventListner) {
|
||||
addBusinessEventListners(businessEvent, businessEventListner, postListners);
|
||||
}
|
||||
|
||||
private void addBusinessEventListners(BUSINESS_EVENTS businessEvent, BusinessEventListner businessEventListner,
|
||||
final Map<BUSINESS_EVENTS, List<BusinessEventListner>> businessEventListnerMap) {
|
||||
List<BusinessEventListner> businessEventListners = businessEventListnerMap.get(businessEvent);
|
||||
if (businessEventListners == null) {
|
||||
businessEventListners = new ArrayList<>();
|
||||
businessEventListnerMap.put(businessEvent, businessEventListners);
|
||||
}
|
||||
businessEventListners.add(businessEventListner);
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -638,6 +638,9 @@ public class LoansApiResource {
|
||||
} else if (is(commandParam, "unassignloanofficer")) {
|
||||
final CommandWrapper commandRequest = builder.unassignLoanOfficer(loanId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
} else if (is(commandParam, "recoverGuarantees")) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().recoverFromGuarantor(loanId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
if (result == null) { throw new UnrecognizedQueryParamException("command", commandParam); }
|
||||
|
||||
+39
-35
@@ -345,6 +345,9 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
@Column(name = "create_standing_instruction_at_disbursement", nullable = true)
|
||||
private Boolean createStandingInstructionAtDisbursement;
|
||||
|
||||
@Column(name = "guarantee_amount_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal guaranteeAmountDerived;
|
||||
|
||||
public static Loan newIndividualLoanApplication(final String accountNo, final Client client, final Integer loanType,
|
||||
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
|
||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||
@@ -586,7 +589,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
* @return
|
||||
*/
|
||||
public LoanTransaction handleChargeAppliedTransaction(final LoanCharge loanCharge, final LocalDate suppliedTransactionDate,
|
||||
final AppUser currentUser) {
|
||||
final AppUser currentUser) {
|
||||
final Money chargeAmount = loanCharge.getAmount(getCurrency());
|
||||
Money feeCharges = chargeAmount;
|
||||
Money penaltyCharges = Money.zero(loanCurrency());
|
||||
@@ -905,7 +908,8 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction waiveLoanChargeTransaction = LoanTransaction.waiveLoanCharge(this, getOffice(), amountWaived,
|
||||
transactionDate, feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser );
|
||||
transactionDate, feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(),
|
||||
currentUser);
|
||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge, waiveLoanChargeTransaction
|
||||
.getAmount(getCurrency()).getAmount(), loanInstallmentNumber);
|
||||
waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
|
||||
@@ -1040,8 +1044,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
this.collateral.addAll(associateWithThisLoan(loanCollateral));
|
||||
}
|
||||
|
||||
public void updateLoanSchedule(final LoanScheduleModel modifiedLoanSchedule,
|
||||
AppUser currentUser) {
|
||||
public void updateLoanSchedule(final LoanScheduleModel modifiedLoanSchedule, AppUser currentUser) {
|
||||
this.repaymentScheduleInstallments.clear();
|
||||
|
||||
for (final LoanScheduleModelPeriod scheduledLoanInstallment : modifiedLoanSchedule.getPeriods()) {
|
||||
@@ -1101,8 +1104,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAccrualsForNonPeriodicAccruals(final Collection<LoanTransaction> accruals,
|
||||
final AppUser currentUser) {
|
||||
private void updateAccrualsForNonPeriodicAccruals(final Collection<LoanTransaction> accruals, final AppUser currentUser) {
|
||||
|
||||
final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged());
|
||||
for (LoanTransaction loanTransaction : accruals) {
|
||||
@@ -2256,8 +2258,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
* Ability to regenerate the repayment schedule based on the loans current
|
||||
* details/state.
|
||||
*/
|
||||
public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
AppUser currentUser) {
|
||||
public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO scheduleGeneratorDTO, AppUser currentUser) {
|
||||
|
||||
final LoanScheduleModel loanSchedule = regenerateScheduleModel(scheduleGeneratorDTO);
|
||||
|
||||
@@ -2489,15 +2490,13 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
|
||||
public ChangedTransactionDetail waiveInterest(final LoanTransaction waiveInterestTransaction,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final AppUser currentUser) {
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
|
||||
validateAccountStatus(LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
|
||||
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
||||
waiveInterestTransaction.getTransactionDate());
|
||||
validateActivityNotBeforeLastTransactionDateForInterestRecalculation(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
||||
waiveInterestTransaction.getTransactionDate());
|
||||
validateActivityNotBeforeLastTransactionDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, waiveInterestTransaction.getTransactionDate());
|
||||
|
||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
@@ -2523,7 +2522,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
|
||||
validateAccountStatus(event);
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(event, repaymentTransaction.getTransactionDate());
|
||||
validateActivityNotBeforeLastTransactionDateForInterestRecalculation(event, repaymentTransaction.getTransactionDate());
|
||||
validateActivityNotBeforeLastTransactionDate(event, repaymentTransaction.getTransactionDate());
|
||||
validateRepaymentDateIsOnHoliday(repaymentTransaction.getTransactionDate(), holidayDetailDTO.isAllowTransactionsOnHoliday(),
|
||||
holidayDetailDTO.getHolidays());
|
||||
validateRepaymentDateIsOnNonWorkingDay(repaymentTransaction.getTransactionDate(), holidayDetailDTO.getWorkingDays(),
|
||||
@@ -2544,8 +2543,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
|
||||
validateAccountStatus(LoanEvent.LOAN_CHARGE_PAYMENT);
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_CHARGE_PAYMENT, paymentTransaction.getTransactionDate());
|
||||
validateActivityNotBeforeLastTransactionDateForInterestRecalculation(LoanEvent.LOAN_CHARGE_PAYMENT,
|
||||
paymentTransaction.getTransactionDate());
|
||||
validateActivityNotBeforeLastTransactionDate(LoanEvent.LOAN_CHARGE_PAYMENT, paymentTransaction.getTransactionDate());
|
||||
validateRepaymentDateIsOnHoliday(paymentTransaction.getTransactionDate(), holidayDetailDTO.isAllowTransactionsOnHoliday(),
|
||||
holidayDetailDTO.getHolidays());
|
||||
validateRepaymentDateIsOnNonWorkingDay(paymentTransaction.getTransactionDate(), holidayDetailDTO.getWorkingDays(),
|
||||
@@ -2936,8 +2934,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
return loanRepaymentScheduleInstallment;
|
||||
}
|
||||
|
||||
public LoanTransaction deriveDefaultInterestWaiverTransaction(
|
||||
final LocalDateTime createdDate, final AppUser currentUser) {
|
||||
public LoanTransaction deriveDefaultInterestWaiverTransaction(final LocalDateTime createdDate, final AppUser currentUser) {
|
||||
|
||||
final Money totalInterestOutstanding = getTotalInterestOutstandingOnLoan();
|
||||
Money possibleInterestToWaive = totalInterestOutstanding.copy();
|
||||
@@ -2968,6 +2965,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
|
||||
HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
|
||||
validateActivityNotBeforeLastTransactionDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, transactionForAdjustment.getTransactionDate());
|
||||
validateRepaymentDateIsOnHoliday(newTransactionDetail.getTransactionDate(), holidayDetailDTO.isAllowTransactionsOnHoliday(),
|
||||
holidayDetailDTO.getHolidays());
|
||||
validateRepaymentDateIsOnNonWorkingDay(newTransactionDetail.getTransactionDate(), holidayDetailDTO.getWorkingDays(),
|
||||
@@ -3009,8 +3007,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail undoWrittenOff(final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final AppUser currentUser) {
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
|
||||
validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
|
||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||
@@ -3031,7 +3028,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
|
||||
private LoanTransaction findWriteOffTransaction() {
|
||||
public LoanTransaction findWriteOffTransaction() {
|
||||
|
||||
LoanTransaction writeOff = null;
|
||||
for (final LoanTransaction transaction : this.loanTransactions) {
|
||||
@@ -3132,8 +3129,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), writtenOffOnLocalDate, txnExternalId,
|
||||
createdDate, currentUser);
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), writtenOffOnLocalDate, txnExternalId, createdDate, currentUser);
|
||||
final boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, this.loanTransactions);
|
||||
if (!isLastTransaction) {
|
||||
final String errorMessage = "The date of the writeoff transaction must occur on or before previous transactions.";
|
||||
@@ -3155,8 +3151,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
private ChangedTransactionDetail closeDisbursements(final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor,
|
||||
final AppUser currentUser) {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final AppUser currentUser) {
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
if (isDisbursementAllowed() && atleastOnceDisbursed()) {
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount());
|
||||
@@ -3236,7 +3231,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
this.closedOnDate = closureDate.toDate();
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), closureDate, txnExternalId,
|
||||
DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
DateUtils.getLocalDateTimeOfTenant(), currentUser);
|
||||
final boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, this.loanTransactions);
|
||||
if (!isLastTransaction) {
|
||||
final String errorMessage = "The closing date of the loan must be on or after latest transaction date.";
|
||||
@@ -3330,7 +3325,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
return status().isSubmittedAndPendingApproval();
|
||||
}
|
||||
|
||||
private boolean isApproved() {
|
||||
public boolean isApproved() {
|
||||
return status().isApproved();
|
||||
}
|
||||
|
||||
@@ -4102,8 +4097,8 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateActivityNotBeforeLastTransactionDateForInterestRecalculation(final LoanEvent event, final LocalDate activityDate) {
|
||||
if (!this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { return; }
|
||||
private void validateActivityNotBeforeLastTransactionDate(final LoanEvent event, final LocalDate activityDate) {
|
||||
if (!(this.repaymentScheduleDetail().isInterestRecalculationEnabled() || this.loanProduct().isHoldGuaranteeFundsEnabled())) { return; }
|
||||
LocalDate lastTransactionDate = getLastUserTransactionDate();
|
||||
final LocalDate clientOfficeJoiningDate = this.client.getOfficeJoiningLocalDate();
|
||||
if (lastTransactionDate.isAfter(activityDate)) {
|
||||
@@ -4332,8 +4327,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
|
||||
public ChangedTransactionDetail updateDisbursementDateForTranche(final LoanDisbursementDetails disbursementDetails,
|
||||
final JsonCommand command, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final Map<String, Object> actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final AppUser currentUser) {
|
||||
final Map<String, Object> actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
|
||||
validateAccountStatus(LoanEvent.LOAN_EDIT_MULTI_DISBURSE_DATE);
|
||||
final LocalDate expectedDisbursementDate = command.localDateValueOfParameterNamed(LoanApiConstants.disbursementDateParameterName);
|
||||
disbursementDetails.updateExpectedDisbursementDate(expectedDisbursementDate.toDate());
|
||||
@@ -4426,8 +4420,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail recalculateScheduleFromLastTransaction(final ScheduleGeneratorDTO generatorDTO,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final AppUser currentUser) {
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser) {
|
||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
/*
|
||||
@@ -4448,7 +4441,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail handleRegenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO,
|
||||
final AppUser currentUser) {
|
||||
final AppUser currentUser) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, currentUser);
|
||||
return processTransactions();
|
||||
|
||||
@@ -4478,8 +4471,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
|
||||
private void regenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO,
|
||||
final AppUser currentUser) {
|
||||
private void regenerateRepaymentScheduleWithInterestRecalculation(final ScheduleGeneratorDTO generatorDTO, final AppUser currentUser) {
|
||||
|
||||
LocalDate lastTransactionDate = getLastUserTransactionDate();
|
||||
generatorDTO.setLastTransactionDate(lastTransactionDate);
|
||||
@@ -4897,4 +4889,16 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
|
||||
return loanCharges;
|
||||
}
|
||||
|
||||
public void setGuaranteeAmount(BigDecimal guaranteeAmountDerived) {
|
||||
this.guaranteeAmountDerived = guaranteeAmountDerived;
|
||||
}
|
||||
|
||||
public void updateGuaranteeAmount(BigDecimal guaranteeAmount) {
|
||||
this.guaranteeAmountDerived = getGuaranteeAmount().add(guaranteeAmount);
|
||||
}
|
||||
|
||||
public BigDecimal getGuaranteeAmount() {
|
||||
return this.guaranteeAmountDerived == null ? BigDecimal.ZERO : this.guaranteeAmountDerived;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -44,7 +44,9 @@ import org.mifosplatform.portfolio.calendar.domain.CalendarInstanceRepository;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarUtils;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
|
||||
import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
|
||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.common.service.BusinessEventNotifierService;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||
@@ -83,6 +85,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
|
||||
private final LoanAccrualWritePlatformService accrualWritePlatformService;
|
||||
private final PlatformSecurityContext context;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
|
||||
@Autowired
|
||||
public LoanAccountDomainServiceJpa(final LoanAssembler loanAccountAssembler, final LoanRepository loanRepository,
|
||||
@@ -95,7 +98,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository,
|
||||
final CalendarInstanceRepository calendarInstanceRepository,
|
||||
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
|
||||
final LoanAccrualWritePlatformService accrualWritePlatformService, final PlatformSecurityContext context) {
|
||||
final LoanAccrualWritePlatformService accrualWritePlatformService, final PlatformSecurityContext context,
|
||||
final BusinessEventNotifierService businessEventNotifierService) {
|
||||
this.loanAccountAssembler = loanAccountAssembler;
|
||||
this.loanRepository = loanRepository;
|
||||
this.loanTransactionRepository = loanTransactionRepository;
|
||||
@@ -112,6 +116,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository;
|
||||
this.accrualWritePlatformService = accrualWritePlatformService;
|
||||
this.context = context;
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -215,6 +220,9 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
|
||||
recalculateAccruals(loan);
|
||||
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT, newRepaymentTransaction);
|
||||
|
||||
builderResult.withEntityId(newRepaymentTransaction.getId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
|
||||
+36
-14
@@ -100,13 +100,13 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
||||
private String externalId;
|
||||
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "created_date", nullable = false)
|
||||
private final Date createdDate;
|
||||
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="appuser_id", nullable = true)
|
||||
@JoinColumn(name = "appuser_id", nullable = true)
|
||||
private final AppUser appUser;
|
||||
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@@ -137,7 +137,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
public static LoanTransaction repayment(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, externalId,
|
||||
createdDate, appUser);
|
||||
createdDate, appUser);
|
||||
}
|
||||
|
||||
public static LoanTransaction recoveryRepayment(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
@@ -148,9 +148,9 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
|
||||
public static LoanTransaction loanPayment(final Loan loan, final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LoanTransactionType transactionType,
|
||||
final LocalDateTime createdDate, final AppUser appUser){
|
||||
return new LoanTransaction(loan, office, transactionType, paymentDetail, amount.getAmount(), paymentDate, externalId,
|
||||
createdDate, appUser);
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, transactionType, paymentDetail, amount.getAmount(), paymentDate, externalId, createdDate,
|
||||
appUser);
|
||||
}
|
||||
|
||||
public static LoanTransaction repaymentAtDisbursement(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
@@ -183,7 +183,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER.getValue(), transferDate.toDateTimeAtStartOfDay()
|
||||
.toDate(), loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary()
|
||||
.getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary()
|
||||
@@ -191,7 +191,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate.toDateTimeAtStartOfDay()
|
||||
.toDate(), loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary()
|
||||
.getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary()
|
||||
@@ -199,7 +199,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate.toDateTimeAtStartOfDay()
|
||||
.toDate(), loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary()
|
||||
.getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary()
|
||||
@@ -209,15 +209,15 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
public static LoanTransaction refund(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REFUND, paymentDetail, amount.getAmount(), paymentDate, externalId,
|
||||
createdDate, appUser);
|
||||
createdDate, appUser);
|
||||
}
|
||||
|
||||
public static LoanTransaction copyTransactionProperties(final LoanTransaction loanTransaction) {
|
||||
return new LoanTransaction(loanTransaction.loan, loanTransaction.office, loanTransaction.typeOf, loanTransaction.dateOf,
|
||||
loanTransaction.amount, loanTransaction.principalPortion, loanTransaction.interestPortion,
|
||||
loanTransaction.feeChargesPortion, loanTransaction.penaltyChargesPortion, loanTransaction.overPaymentPortion,
|
||||
loanTransaction.reversed, loanTransaction.paymentDetail, loanTransaction.externalId,
|
||||
new LocalDateTime(loanTransaction.createdDate), loanTransaction.appUser);
|
||||
loanTransaction.reversed, loanTransaction.paymentDetail, loanTransaction.externalId, new LocalDateTime(
|
||||
loanTransaction.createdDate), loanTransaction.appUser);
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueLoanCharge(final Loan loan, final Office office, final Money amount, final LocalDate applyDate,
|
||||
@@ -274,7 +274,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public static LoanTransaction writeoff(final Loan loan, final Office office, final LocalDate writeOffDate, final String externalId,
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
final LocalDateTime createdDate, final AppUser appUser) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WRITEOFF, null, writeOffDate, externalId, createdDate, appUser);
|
||||
}
|
||||
|
||||
@@ -621,4 +621,26 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
|
||||
public void manuallyAdjustedOrReversed() {
|
||||
this.manuallyAdjustedOrReversed = true;
|
||||
}
|
||||
|
||||
private LocalDate getCreatedDate() {
|
||||
return new LocalDate(this.createdDate);
|
||||
}
|
||||
|
||||
public boolean isLastTransaction(final LoanTransaction loanTransaction) {
|
||||
boolean isLatest = false;
|
||||
if (loanTransaction != null) {
|
||||
isLatest = this.getTransactionDate().isBefore(loanTransaction.getTransactionDate())
|
||||
|| (this.getTransactionDate().isEqual(loanTransaction.getTransactionDate()) && this.getCreatedDate().isBefore(
|
||||
loanTransaction.getCreatedDate()));
|
||||
}
|
||||
return isLatest;
|
||||
}
|
||||
|
||||
public boolean isLatestTransaction(final LoanTransaction loanTransaction) {
|
||||
boolean isLatest = false;
|
||||
if (loanTransaction != null) {
|
||||
isLatest = this.getCreatedDate().isBefore(loanTransaction.getCreatedDate());
|
||||
}
|
||||
return isLatest;
|
||||
}
|
||||
}
|
||||
+7
@@ -47,4 +47,11 @@ public class GuarantorConstants {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String GUARANTOR_SELF_GUARANTEE_ERROR = "min.self.guarantee.required";
|
||||
public static final String GUARANTOR_EXTERNAL_GUARANTEE_ERROR = "min.external.guarantee.required";
|
||||
public static final String GUARANTOR_MANDATORY_GUARANTEE_ERROR = "mandated.guarantee.required";
|
||||
public static final String GUARANTOR_INSUFFICIENT_BALANCE_ERROR = "insufficient.balance";
|
||||
public static final String GUARANTOR_NOT_ACTIVE_ERROR = "not.active";
|
||||
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
|
||||
|
||||
public class GuarantorDTO {
|
||||
|
||||
private BigDecimal paidAmount;
|
||||
private Loan loan;
|
||||
|
||||
}
|
||||
+8
@@ -345,4 +345,12 @@ public class Guarantor extends AbstractPersistable<Long> {
|
||||
}
|
||||
return hasGuarantee;
|
||||
}
|
||||
|
||||
public boolean isSelfGuarantee() {
|
||||
boolean isSelf = false;
|
||||
if (isExistingCustomer() && getEntityId().equals(getClientId())) {
|
||||
isSelf = true;
|
||||
}
|
||||
return isSelf;
|
||||
}
|
||||
}
|
||||
+56
-5
@@ -20,6 +20,7 @@ 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.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@@ -46,7 +47,7 @@ public class GuarantorFundingDetails extends AbstractPersistable<Long> {
|
||||
|
||||
@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;
|
||||
|
||||
@@ -70,12 +71,62 @@ public class GuarantorFundingDetails extends AbstractPersistable<Long> {
|
||||
public void updateStatus(final GuarantorFundStatusType guarantorFundStatusType) {
|
||||
this.status = guarantorFundStatusType.getValue();
|
||||
}
|
||||
|
||||
public GuarantorFundStatusType getStatus(){
|
||||
|
||||
public GuarantorFundStatusType getStatus() {
|
||||
return GuarantorFundStatusType.fromInt(this.status);
|
||||
}
|
||||
|
||||
public SavingsAccount getLinkedSavingsAccount(){
|
||||
|
||||
public SavingsAccount getLinkedSavingsAccount() {
|
||||
return accountAssociations.linkedSavingsAccount();
|
||||
}
|
||||
|
||||
public Loan getLoanAccount() {
|
||||
return this.guarantor.getLoan();
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public BigDecimal getAmountReleased() {
|
||||
return this.amountReleased == null ? BigDecimal.ZERO : this.amountReleased;
|
||||
}
|
||||
|
||||
public BigDecimal getAmountRemaining() {
|
||||
return this.amountRemaining == null ? BigDecimal.ZERO : this.amountRemaining;
|
||||
}
|
||||
|
||||
public BigDecimal getAmountTransfered() {
|
||||
return this.amountTransfered == null ? BigDecimal.ZERO : this.amountTransfered;
|
||||
}
|
||||
|
||||
public void releaseFunds(final BigDecimal amount) {
|
||||
this.amountReleased = getAmountReleased().add(amount);
|
||||
this.amountRemaining = getAmountRemaining().subtract(amount);
|
||||
if (this.amountRemaining.compareTo(BigDecimal.ZERO) == 0) {
|
||||
this.updateStatus(GuarantorFundStatusType.COMPLETED);
|
||||
}
|
||||
}
|
||||
|
||||
public void undoReleaseFunds(final BigDecimal amount) {
|
||||
this.amountReleased = getAmountReleased().subtract(amount);
|
||||
this.amountRemaining = getAmountRemaining().add(amount);
|
||||
if (getStatus().isCompleted() && this.amountRemaining.compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.updateStatus(GuarantorFundStatusType.ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
public void withdrawFunds(final BigDecimal amount) {
|
||||
this.amountTransfered = amount;
|
||||
}
|
||||
|
||||
public void addGuarantorFundingTransactions(final GuarantorFundingTransaction guarantorFundingTransaction) {
|
||||
this.guarantorFundingTransactions.add(guarantorFundingTransaction);
|
||||
}
|
||||
|
||||
public void undoAllTransactions() {
|
||||
for (GuarantorFundingTransaction fundingTransaction : this.guarantorFundingTransactions) {
|
||||
fundingTransaction.reverseTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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 org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface GuarantorFundingRepository extends JpaRepository<GuarantorFundingDetails, Long>,
|
||||
JpaSpecificationExecutor<GuarantorFundingDetails> {}
|
||||
+26
-2
@@ -5,10 +5,13 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.guarantor.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||
@@ -24,14 +27,35 @@ public class GuarantorFundingTransaction extends AbstractPersistable<Long> {
|
||||
private GuarantorFundingDetails guarantorFundingDetails;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "loan_transaction_id", nullable = false)
|
||||
@JoinColumn(name = "loan_transaction_id", nullable = true)
|
||||
private LoanTransaction loanTransaction;
|
||||
|
||||
@ManyToOne
|
||||
@OneToOne
|
||||
@JoinColumn(name = "deposit_on_hold_transaction_id", nullable = false)
|
||||
private DepositAccountOnHoldTransaction depositAccountOnHoldTransaction;
|
||||
|
||||
@Column(name = "is_reversed", nullable = false)
|
||||
private boolean reversed;
|
||||
|
||||
protected GuarantorFundingTransaction() {}
|
||||
|
||||
public GuarantorFundingTransaction(final GuarantorFundingDetails guarantorFundingDetails, final LoanTransaction loanTransaction,
|
||||
final DepositAccountOnHoldTransaction depositAccountOnHoldTransaction) {
|
||||
this.depositAccountOnHoldTransaction = depositAccountOnHoldTransaction;
|
||||
this.guarantorFundingDetails = guarantorFundingDetails;
|
||||
this.loanTransaction = loanTransaction;
|
||||
this.reversed = false;
|
||||
}
|
||||
|
||||
public void reverseTransaction() {
|
||||
if (!this.reversed) {
|
||||
this.reversed = true;
|
||||
BigDecimal amountForReverse = this.depositAccountOnHoldTransaction.getAmount();
|
||||
this.depositAccountOnHoldTransaction.reverseTransaction();
|
||||
if (this.depositAccountOnHoldTransaction.getTransactionType().isRelease()) {
|
||||
this.guarantorFundingDetails.undoReleaseFunds(amountForReverse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface GuarantorFundingTransactionRepository extends JpaRepository<GuarantorFundingTransaction, Long>,
|
||||
JpaSpecificationExecutor<GuarantorFundingTransaction> {
|
||||
|
||||
@Query("from GuarantorFundingTransaction ft where ft.loanTransaction.id in (:loanTransactions)")
|
||||
List<GuarantorFundingTransaction> fetchGuarantorFundingTransactions(@Param("loanTransactions") List<Long> loanTransactions);
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.service;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingDetails;
|
||||
|
||||
public interface GuarantorDomainService {
|
||||
|
||||
void releaseGuarantor(GuarantorFundingDetails guarantorFundingDetails, LocalDate transactionDate);
|
||||
|
||||
void validateGuarantorBusinessRules(Loan loan);
|
||||
|
||||
void assignGuarantor(GuarantorFundingDetails guarantorFundingDetails, LocalDate transactionDate);
|
||||
|
||||
void transaferFundsFromGuarantor(Loan loan);
|
||||
|
||||
}
|
||||
+558
@@ -0,0 +1,558 @@
|
||||
/**
|
||||
* 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.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.portfolio.account.PortfolioAccountType;
|
||||
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
|
||||
import org.mifosplatform.portfolio.account.domain.AccountTransferDetails;
|
||||
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
|
||||
import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
|
||||
import org.mifosplatform.portfolio.common.service.BusinessEventListner;
|
||||
import org.mifosplatform.portfolio.common.service.BusinessEventNotifierService;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.GuarantorConstants;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.Guarantor;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingDetails;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingRepository;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingTransaction;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingTransactionRepository;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorRepository;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductGuaranteeDetails;
|
||||
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.mifosplatform.portfolio.savings.domain.DepositAccountOnHoldTransaction;
|
||||
import org.mifosplatform.portfolio.savings.domain.DepositAccountOnHoldTransactionRepository;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
||||
|
||||
private final GuarantorRepository guarantorRepository;
|
||||
private final GuarantorFundingRepository guarantorFundingRepository;
|
||||
private final GuarantorFundingTransactionRepository guarantorFundingTransactionRepository;
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository;
|
||||
private final Map<Long, Long> releaseLoanIds = new HashMap<>(2);
|
||||
private final RoundingMode roundingMode = RoundingMode.HALF_EVEN;
|
||||
|
||||
@Autowired
|
||||
public GuarantorDomainServiceImpl(final GuarantorRepository guarantorRepository,
|
||||
final GuarantorFundingRepository guarantorFundingRepository,
|
||||
final GuarantorFundingTransactionRepository guarantorFundingTransactionRepository,
|
||||
final AccountTransfersWritePlatformService accountTransfersWritePlatformService,
|
||||
final BusinessEventNotifierService businessEventNotifierService,
|
||||
final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository) {
|
||||
this.guarantorRepository = guarantorRepository;
|
||||
this.guarantorFundingRepository = guarantorFundingRepository;
|
||||
this.guarantorFundingTransactionRepository = guarantorFundingTransactionRepository;
|
||||
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
this.depositAccountOnHoldTransactionRepository = depositAccountOnHoldTransactionRepository;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void addListners() {
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_APPROVED, new ValidateOnBusinessEvent());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_APPROVED, new HoldFundsOnBusinessEvent());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_UNDO_APPROVAL, new UndoAllFundTransactions());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_UNDO_DISBURSAL,
|
||||
new ReverseAllFundsOnBusinessEvent());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_UNDO_TRANSACTION,
|
||||
new ReverseFundsOnBusinessEvent());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT,
|
||||
new ReleaseFundsOnBusinessEvent());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_WRITTEN_OFF, new ReleaseAllFunds());
|
||||
this.businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_UNDO_WRITTEN_OFF,
|
||||
new ReverseFundsOnBusinessEvent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateGuarantorBusinessRules(Loan loan) {
|
||||
LoanProduct loanProduct = loan.loanProduct();
|
||||
BigDecimal principal = loan.getPrincpal().getAmount();
|
||||
if (loanProduct.isHoldGuaranteeFundsEnabled()) {
|
||||
LoanProductGuaranteeDetails guaranteeData = loanProduct.getLoanProductGuaranteeDetails();
|
||||
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
|
||||
BigDecimal mandatoryAmount = principal.multiply(guaranteeData.getMandatoryGuarantee()).divide(BigDecimal.valueOf(100));
|
||||
BigDecimal minSelfAmount = principal.multiply(guaranteeData.getMinimumGuaranteeFromOwnFunds()).divide(BigDecimal.valueOf(100));
|
||||
BigDecimal minExtGuarantee = principal.multiply(guaranteeData.getMinimumGuaranteeFromGuarantor()).divide(
|
||||
BigDecimal.valueOf(100));
|
||||
|
||||
BigDecimal actualAmount = BigDecimal.ZERO;
|
||||
BigDecimal actualSelfAmount = BigDecimal.ZERO;
|
||||
BigDecimal actualExtGuarantee = BigDecimal.ZERO;
|
||||
for (Guarantor guarantor : existGuarantorList) {
|
||||
List<GuarantorFundingDetails> fundingDetails = guarantor.getGuarantorFundDetails();
|
||||
for (GuarantorFundingDetails guarantorFundingDetails : fundingDetails) {
|
||||
if (guarantorFundingDetails.getStatus().isActive() || guarantorFundingDetails.getStatus().isWithdrawn()
|
||||
|| guarantorFundingDetails.getStatus().isCompleted()) {
|
||||
if (guarantor.isSelfGuarantee()) {
|
||||
actualSelfAmount = actualSelfAmount.add(guarantorFundingDetails.getAmount()).subtract(
|
||||
guarantorFundingDetails.getAmountTransfered());
|
||||
} else {
|
||||
actualExtGuarantee = actualExtGuarantee.add(guarantorFundingDetails.getAmount()).subtract(
|
||||
guarantorFundingDetails.getAmountTransfered());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.guarantor");
|
||||
if (actualSelfAmount.compareTo(minSelfAmount) == -1) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_SELF_GUARANTEE_ERROR,
|
||||
minSelfAmount);
|
||||
}
|
||||
|
||||
if (actualExtGuarantee.compareTo(minExtGuarantee) == -1) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_EXTERNAL_GUARANTEE_ERROR,
|
||||
minExtGuarantee);
|
||||
}
|
||||
actualAmount = actualAmount.add(actualExtGuarantee).add(actualSelfAmount);
|
||||
if (actualAmount.compareTo(mandatoryAmount) == -1) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_MANDATORY_GUARANTEE_ERROR,
|
||||
mandatoryAmount);
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignGuarantor(final GuarantorFundingDetails guarantorFundingDetails, final LocalDate transactionDate) {
|
||||
if (guarantorFundingDetails.getStatus().isActive()) {
|
||||
SavingsAccount savingsAccount = guarantorFundingDetails.getLinkedSavingsAccount();
|
||||
savingsAccount.holdFunds(guarantorFundingDetails.getAmount());
|
||||
if (savingsAccount.getWithdrawableBalance().compareTo(BigDecimal.ZERO) == -1) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.guarantor");
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_INSUFFICIENT_BALANCE_ERROR,
|
||||
savingsAccount.getId());
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
}
|
||||
DepositAccountOnHoldTransaction onHoldTransaction = DepositAccountOnHoldTransaction.hold(savingsAccount,
|
||||
guarantorFundingDetails.getAmount(), transactionDate);
|
||||
GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails, null,
|
||||
onHoldTransaction);
|
||||
guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction);
|
||||
this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseGuarantor(final GuarantorFundingDetails guarantorFundingDetails, final LocalDate transactionDate) {
|
||||
BigDecimal amoutForWithdraw = guarantorFundingDetails.getAmountRemaining();
|
||||
if (amoutForWithdraw.compareTo(BigDecimal.ZERO) == 1 && (guarantorFundingDetails.getStatus().isActive())) {
|
||||
SavingsAccount savingsAccount = guarantorFundingDetails.getLinkedSavingsAccount();
|
||||
savingsAccount.releaseFunds(amoutForWithdraw);
|
||||
DepositAccountOnHoldTransaction onHoldTransaction = DepositAccountOnHoldTransaction.release(savingsAccount, amoutForWithdraw,
|
||||
transactionDate);
|
||||
GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails, null,
|
||||
onHoldTransaction);
|
||||
guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction);
|
||||
guarantorFundingDetails.releaseFunds(amoutForWithdraw);
|
||||
guarantorFundingDetails.withdrawFunds(amoutForWithdraw);
|
||||
guarantorFundingDetails.getLoanAccount().updateGuaranteeAmount(amoutForWithdraw.negate());
|
||||
this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction);
|
||||
this.guarantorFundingRepository.save(guarantorFundingDetails);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transaferFundsFromGuarantor(final Loan loan) {
|
||||
if (loan.getGuaranteeAmount().compareTo(BigDecimal.ZERO) != 1) { return; }
|
||||
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = true;
|
||||
LocalDate transactionDate = LocalDate.now();
|
||||
PortfolioAccountType fromAccountType = PortfolioAccountType.SAVINGS;
|
||||
PortfolioAccountType toAccountType = PortfolioAccountType.LOAN;
|
||||
final Long toAccountId = loan.getId();
|
||||
final String description = "Payment from guarantor savings";
|
||||
final Locale locale = null;
|
||||
final DateTimeFormatter fmt = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Integer fromTransferType = null;
|
||||
final Integer toTransferType = null;
|
||||
final Long chargeId = null;
|
||||
final Integer loanInstallmentNumber = null;
|
||||
final Integer transferType = AccountTransferType.LOAN_REPAYMENT.getValue();
|
||||
final AccountTransferDetails accountTransferDetails = null;
|
||||
final String noteText = null;
|
||||
|
||||
final String txnExternalId = null;
|
||||
final SavingsAccount toSavingsAccount = null;
|
||||
|
||||
Long loanId = loan.getId();
|
||||
|
||||
for (Guarantor guarantor : existGuarantorList) {
|
||||
final List<GuarantorFundingDetails> fundingDetails = guarantor.getGuarantorFundDetails();
|
||||
for (GuarantorFundingDetails guarantorFundingDetails : fundingDetails) {
|
||||
if (guarantorFundingDetails.getStatus().isActive()) {
|
||||
final SavingsAccount fromSavingsAccount = guarantorFundingDetails.getLinkedSavingsAccount();
|
||||
final Long fromAccountId = fromSavingsAccount.getId();
|
||||
releaseLoanIds.put(loanId, guarantorFundingDetails.getId());
|
||||
try {
|
||||
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate,
|
||||
guarantorFundingDetails.getAmountRemaining(), fromAccountType, toAccountType, fromAccountId, toAccountId,
|
||||
description, locale, fmt, paymentDetail, fromTransferType, toTransferType, chargeId, loanInstallmentNumber,
|
||||
transferType, accountTransferDetails, noteText, txnExternalId, loan, toSavingsAccount, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferAmount(accountTransferDTO);
|
||||
} finally {
|
||||
releaseLoanIds.remove(loanId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accountTransferDTO
|
||||
*/
|
||||
private void transferAmount(final AccountTransferDTO accountTransferDTO) {
|
||||
try {
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} catch (final InsufficientAccountBalanceException e) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.guarantor");
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_INSUFFICIENT_BALANCE_ERROR,
|
||||
accountTransferDTO.getFromAccountId(), accountTransferDTO.getToAccountId());
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void reverseAllFundTransaction(final Loan loan) {
|
||||
|
||||
if (loan.getGuaranteeAmount().compareTo(BigDecimal.ZERO) == 1) {
|
||||
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
|
||||
List<GuarantorFundingDetails> guarantorFundingDetailList = new ArrayList<>();
|
||||
for (Guarantor guarantor : existGuarantorList) {
|
||||
final List<GuarantorFundingDetails> fundingDetails = guarantor.getGuarantorFundDetails();
|
||||
for (GuarantorFundingDetails guarantorFundingDetails : fundingDetails) {
|
||||
guarantorFundingDetails.undoAllTransactions();
|
||||
guarantorFundingDetailList.add(guarantorFundingDetails);
|
||||
}
|
||||
}
|
||||
|
||||
if (!guarantorFundingDetailList.isEmpty()) {
|
||||
loan.setGuaranteeAmount(null);
|
||||
this.guarantorFundingRepository.save(guarantorFundingDetailList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void holdGuarantorFunds(final Loan loan) {
|
||||
if (loan.loanProduct().isHoldGuaranteeFundsEnabled()) {
|
||||
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
|
||||
List<GuarantorFundingDetails> guarantorFundingDetailList = new ArrayList<>();
|
||||
List<DepositAccountOnHoldTransaction> onHoldTransactions = new ArrayList<>();
|
||||
BigDecimal totalGuarantee = BigDecimal.ZERO;
|
||||
List<Long> insufficientBalanceIds = new ArrayList<>();
|
||||
for (Guarantor guarantor : existGuarantorList) {
|
||||
final List<GuarantorFundingDetails> fundingDetails = guarantor.getGuarantorFundDetails();
|
||||
for (GuarantorFundingDetails guarantorFundingDetails : fundingDetails) {
|
||||
if (guarantorFundingDetails.getStatus().isActive()) {
|
||||
SavingsAccount savingsAccount = guarantorFundingDetails.getLinkedSavingsAccount();
|
||||
savingsAccount.holdFunds(guarantorFundingDetails.getAmount());
|
||||
totalGuarantee = totalGuarantee.add(guarantorFundingDetails.getAmount());
|
||||
DepositAccountOnHoldTransaction onHoldTransaction = DepositAccountOnHoldTransaction.hold(savingsAccount,
|
||||
guarantorFundingDetails.getAmount(), loan.getApprovedOnDate());
|
||||
onHoldTransactions.add(onHoldTransaction);
|
||||
GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails,
|
||||
null, onHoldTransaction);
|
||||
guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction);
|
||||
guarantorFundingDetailList.add(guarantorFundingDetails);
|
||||
if (savingsAccount.getWithdrawableBalance().compareTo(BigDecimal.ZERO) == -1) {
|
||||
insufficientBalanceIds.add(savingsAccount.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!insufficientBalanceIds.isEmpty()) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.guarantor");
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_INSUFFICIENT_BALANCE_ERROR,
|
||||
insufficientBalanceIds);
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
|
||||
}
|
||||
loan.setGuaranteeAmount(totalGuarantee);
|
||||
if (!guarantorFundingDetailList.isEmpty()) {
|
||||
this.depositAccountOnHoldTransactionRepository.save(onHoldTransactions);
|
||||
this.guarantorFundingRepository.save(guarantorFundingDetailList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseGuarantorFunds(final LoanTransaction loanTransaction) {
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
if (loan.getGuaranteeAmount().compareTo(BigDecimal.ZERO) == 1) {
|
||||
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
|
||||
List<GuarantorFundingDetails> externalGuarantorList = new ArrayList<>();
|
||||
List<GuarantorFundingDetails> selfGuarantorList = new ArrayList<>();
|
||||
BigDecimal selfGuarantee = BigDecimal.ZERO;
|
||||
BigDecimal guarantorGuarantee = BigDecimal.ZERO;
|
||||
for (Guarantor guarantor : existGuarantorList) {
|
||||
final List<GuarantorFundingDetails> fundingDetails = guarantor.getGuarantorFundDetails();
|
||||
for (GuarantorFundingDetails guarantorFundingDetails : fundingDetails) {
|
||||
if (guarantorFundingDetails.getStatus().isActive()) {
|
||||
if (guarantor.isSelfGuarantee()) {
|
||||
selfGuarantorList.add(guarantorFundingDetails);
|
||||
selfGuarantee = selfGuarantee.add(guarantorFundingDetails.getAmountRemaining());
|
||||
} else if (guarantor.isExistingCustomer()) {
|
||||
externalGuarantorList.add(guarantorFundingDetails);
|
||||
guarantorGuarantee = guarantorGuarantee.add(guarantorFundingDetails.getAmountRemaining());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BigDecimal amountForRelease = loanTransaction.getPrincipalPortion();
|
||||
BigDecimal totalGuaranteeAmount = loan.getGuaranteeAmount();
|
||||
BigDecimal principal = loan.getPrincpal().getAmount();
|
||||
|
||||
amountForRelease = amountForRelease.multiply(totalGuaranteeAmount).divide(principal);
|
||||
List<DepositAccountOnHoldTransaction> accountOnHoldTransactions = new ArrayList<>();
|
||||
|
||||
BigDecimal amountLeft = calculateAndRelaseGuarantorFunds(externalGuarantorList, guarantorGuarantee, amountForRelease,
|
||||
loanTransaction, accountOnHoldTransactions);
|
||||
|
||||
if (amountLeft.compareTo(BigDecimal.ZERO) == 1) {
|
||||
calculateAndRelaseGuarantorFunds(selfGuarantorList, selfGuarantee, amountLeft, loanTransaction, accountOnHoldTransactions);
|
||||
externalGuarantorList.addAll(selfGuarantorList);
|
||||
}
|
||||
|
||||
if (!externalGuarantorList.isEmpty()) {
|
||||
this.depositAccountOnHoldTransactionRepository.save(accountOnHoldTransactions);
|
||||
this.guarantorFundingRepository.save(externalGuarantorList);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void releaseAllGuarantors(final LoanTransaction loanTransaction) {
|
||||
Loan loan = loanTransaction.getLoan();
|
||||
if (loan.getGuaranteeAmount().compareTo(BigDecimal.ZERO) == 1) {
|
||||
final List<Guarantor> existGuarantorList = this.guarantorRepository.findByLoan(loan);
|
||||
List<GuarantorFundingDetails> saveGuarantorFundingDetails = new ArrayList<>();
|
||||
List<DepositAccountOnHoldTransaction> onHoldTransactions = new ArrayList<>();
|
||||
for (Guarantor guarantor : existGuarantorList) {
|
||||
final List<GuarantorFundingDetails> fundingDetails = guarantor.getGuarantorFundDetails();
|
||||
for (GuarantorFundingDetails guarantorFundingDetails : fundingDetails) {
|
||||
BigDecimal amoutForRelease = guarantorFundingDetails.getAmountRemaining();
|
||||
if (amoutForRelease.compareTo(BigDecimal.ZERO) == 1 && (guarantorFundingDetails.getStatus().isActive())) {
|
||||
SavingsAccount savingsAccount = guarantorFundingDetails.getLinkedSavingsAccount();
|
||||
savingsAccount.releaseFunds(amoutForRelease);
|
||||
DepositAccountOnHoldTransaction onHoldTransaction = DepositAccountOnHoldTransaction.release(savingsAccount,
|
||||
amoutForRelease, loanTransaction.getTransactionDate());
|
||||
onHoldTransactions.add(onHoldTransaction);
|
||||
GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails,
|
||||
loanTransaction, onHoldTransaction);
|
||||
guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction);
|
||||
guarantorFundingDetails.releaseFunds(amoutForRelease);
|
||||
saveGuarantorFundingDetails.add(guarantorFundingDetails);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!saveGuarantorFundingDetails.isEmpty()) {
|
||||
this.depositAccountOnHoldTransactionRepository.save(onHoldTransactions);
|
||||
this.guarantorFundingRepository.save(saveGuarantorFundingDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void completeGuarantorFund(final LoanTransaction loanTransaction) {
|
||||
Loan loan = loanTransaction.getLoan();
|
||||
GuarantorFundingDetails guarantorFundingDetails = this.guarantorFundingRepository.findOne(releaseLoanIds.get(loan.getId()));
|
||||
if (guarantorFundingDetails != null) {
|
||||
BigDecimal amountForRelease = loanTransaction.getAmount(loan.getCurrency()).getAmount();
|
||||
BigDecimal guarantorGuarantee = amountForRelease;
|
||||
List<GuarantorFundingDetails> guarantorList = Arrays.asList(guarantorFundingDetails);
|
||||
final List<DepositAccountOnHoldTransaction> accountOnHoldTransactions = new ArrayList<>();
|
||||
calculateAndRelaseGuarantorFunds(guarantorList, guarantorGuarantee, amountForRelease, loanTransaction,
|
||||
accountOnHoldTransactions);
|
||||
this.depositAccountOnHoldTransactionRepository.save(accountOnHoldTransactions);
|
||||
this.guarantorFundingRepository.save(guarantorFundingDetails);
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal calculateAndRelaseGuarantorFunds(List<GuarantorFundingDetails> guarantorList, BigDecimal totalGuaranteeAmount,
|
||||
BigDecimal amountForRelease, LoanTransaction loanTransaction,
|
||||
final List<DepositAccountOnHoldTransaction> accountOnHoldTransactions) {
|
||||
BigDecimal amountLeft = amountForRelease;
|
||||
for (GuarantorFundingDetails fundingDetails : guarantorList) {
|
||||
BigDecimal guarantorAmount = amountForRelease.multiply(fundingDetails.getAmountRemaining()).divide(totalGuaranteeAmount,
|
||||
roundingMode);
|
||||
if (fundingDetails.getAmountRemaining().compareTo(guarantorAmount) < 1) {
|
||||
guarantorAmount = fundingDetails.getAmountRemaining();
|
||||
}
|
||||
fundingDetails.releaseFunds(guarantorAmount);
|
||||
SavingsAccount savingsAccount = fundingDetails.getLinkedSavingsAccount();
|
||||
savingsAccount.releaseFunds(guarantorAmount);
|
||||
DepositAccountOnHoldTransaction onHoldTransaction = DepositAccountOnHoldTransaction.release(savingsAccount, guarantorAmount,
|
||||
loanTransaction.getTransactionDate());
|
||||
accountOnHoldTransactions.add(onHoldTransaction);
|
||||
GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(fundingDetails, loanTransaction,
|
||||
onHoldTransaction);
|
||||
fundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction);
|
||||
amountLeft = amountLeft.subtract(guarantorAmount);
|
||||
}
|
||||
return amountLeft;
|
||||
}
|
||||
|
||||
private void reverseTransaction(final List<Long> loanTransactionIds) {
|
||||
|
||||
List<GuarantorFundingTransaction> fundingTransactions = this.guarantorFundingTransactionRepository
|
||||
.fetchGuarantorFundingTransactions(loanTransactionIds);
|
||||
for (GuarantorFundingTransaction fundingTransaction : fundingTransactions) {
|
||||
fundingTransaction.reverseTransaction();
|
||||
}
|
||||
if (!fundingTransactions.isEmpty()) {
|
||||
this.guarantorFundingTransactionRepository.save(fundingTransactions);
|
||||
}
|
||||
}
|
||||
|
||||
private class ValidateOnBusinessEvent implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof Loan) {
|
||||
Loan loan = (Loan) businessEventEntity;
|
||||
validateGuarantorBusinessRules(loan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class HoldFundsOnBusinessEvent implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof Loan) {
|
||||
Loan loan = (Loan) businessEventEntity;
|
||||
holdGuarantorFunds(loan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReleaseFundsOnBusinessEvent implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof LoanTransaction) {
|
||||
LoanTransaction loanTransaction = (LoanTransaction) businessEventEntity;
|
||||
if (releaseLoanIds.containsKey(loanTransaction.getLoan().getId())) {
|
||||
completeGuarantorFund(loanTransaction);
|
||||
} else {
|
||||
releaseGuarantorFunds(loanTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReverseFundsOnBusinessEvent implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof LoanTransaction) {
|
||||
LoanTransaction loanTransaction = (LoanTransaction) businessEventEntity;
|
||||
List<Long> reersedTransactions = new ArrayList<>(1);
|
||||
reersedTransactions.add(loanTransaction.getId());
|
||||
reverseTransaction(reersedTransactions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReverseAllFundsOnBusinessEvent implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof Loan) {
|
||||
Loan loan = (Loan) businessEventEntity;
|
||||
List<Long> reersedTransactions = new ArrayList<>(1);
|
||||
reersedTransactions.addAll(loan.findExistingTransactionIds());
|
||||
reverseTransaction(reersedTransactions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class UndoAllFundTransactions implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof Loan) {
|
||||
Loan loan = (Loan) businessEventEntity;
|
||||
reverseAllFundTransaction(loan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReleaseAllFunds implements BusinessEventListner {
|
||||
|
||||
@Override
|
||||
public void businessEventToBeExecuted(@SuppressWarnings("unused") AbstractPersistable<Long> businessEventEntity) {}
|
||||
|
||||
@Override
|
||||
public void businessEventWasExecuted(AbstractPersistable<Long> businessEventEntity) {
|
||||
if (businessEventEntity instanceof LoanTransaction) {
|
||||
LoanTransaction loanTransaction = (LoanTransaction) businessEventEntity;
|
||||
releaseAllGuarantors(loanTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+42
-6
@@ -10,11 +10,15 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.account.domain.AccountAssociationType;
|
||||
@@ -57,13 +61,14 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
private final AccountAssociationsRepository accountAssociationsRepository;
|
||||
private final GuarantorDomainService guarantorDomainService;
|
||||
|
||||
@Autowired
|
||||
public GuarantorWritePlatformServiceJpaRepositoryIImpl(final LoanRepositoryWrapper loanRepositoryWrapper,
|
||||
final GuarantorRepository guarantorRepository, final ClientRepositoryWrapper clientRepositoryWrapper,
|
||||
final StaffRepositoryWrapper staffRepositoryWrapper, final GuarantorCommandFromApiJsonDeserializer fromApiJsonDeserializer,
|
||||
final CodeValueRepositoryWrapper codeValueRepositoryWrapper, final SavingsAccountAssembler savingsAccountAssembler,
|
||||
final AccountAssociationsRepository accountAssociationsRepository) {
|
||||
final AccountAssociationsRepository accountAssociationsRepository, final GuarantorDomainService guarantorDomainService) {
|
||||
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
||||
this.clientRepositoryWrapper = clientRepositoryWrapper;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
@@ -72,6 +77,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
this.codeValueRepositoryWrapper = codeValueRepositoryWrapper;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
this.accountAssociationsRepository = accountAssociationsRepository;
|
||||
this.guarantorDomainService = guarantorDomainService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,6 +93,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
final Collection<Guarantor> existGuarantorList) {
|
||||
try {
|
||||
guarantorCommand.validateForCreate();
|
||||
validateLoanStatus(loan);
|
||||
final List<GuarantorFundingDetails> guarantorFundingDetails = new ArrayList<>();
|
||||
AccountAssociations accountAssociations = null;
|
||||
if (guarantorCommand.getSavingsId() != null) {
|
||||
@@ -97,6 +104,11 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
GuarantorFundingDetails fundingDetails = new GuarantorFundingDetails(accountAssociations,
|
||||
GuarantorFundStatusType.ACTIVE.getValue(), guarantorCommand.getAmount());
|
||||
guarantorFundingDetails.add(fundingDetails);
|
||||
if (loan.isDisbursed() || loan.isApproved()
|
||||
|| (loan.getGuaranteeAmount() != null || loan.loanProduct().isHoldGuaranteeFundsEnabled())) {
|
||||
this.guarantorDomainService.assignGuarantor(fundingDetails, LocalDate.now());
|
||||
loan.updateGuaranteeAmount(fundingDetails.getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
final Long clientRelationshipId = guarantorCommand.getClientRelationshipTypeId();
|
||||
@@ -162,6 +174,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
guarantorCommand.validateForUpdate();
|
||||
|
||||
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||
validateLoanStatus(loan);
|
||||
final Guarantor guarantorForUpdate = this.guarantorRepository.findByLoanAndId(loan, guarantorId);
|
||||
if (guarantorForUpdate == null) { throw new GuarantorNotFoundException(loanId, guarantorId); }
|
||||
|
||||
@@ -214,27 +227,42 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
@Transactional
|
||||
public CommandProcessingResult removeGuarantor(final Long loanId, final Long guarantorId, final Long guarantorFundingId) {
|
||||
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||
validateLoanStatus(loan);
|
||||
final Guarantor guarantorForDelete = this.guarantorRepository.findByLoanAndId(loan, guarantorId);
|
||||
if (guarantorForDelete == null || (guarantorFundingId == null && !guarantorForDelete.getGuarantorFundDetails().isEmpty())) { throw new GuarantorNotFoundException(
|
||||
loanId, guarantorId, guarantorFundingId); }
|
||||
return removeGuarantor(guarantorForDelete, loanId, guarantorFundingId);
|
||||
CommandProcessingResult commandProcessingResult = removeGuarantor(guarantorForDelete, loanId, guarantorFundingId);
|
||||
this.guarantorDomainService.validateGuarantorBusinessRules(loan);
|
||||
return commandProcessingResult;
|
||||
}
|
||||
|
||||
private CommandProcessingResult removeGuarantor(final Guarantor guarantorForDelete, final Long loanId, final Long guarantorFundingId) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("Guarantor");
|
||||
|
||||
if (guarantorFundingId == null) {
|
||||
if (!guarantorForDelete.isActive()) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_NOT_ACTIVE_ERROR);
|
||||
}
|
||||
guarantorForDelete.updateStatus(false);
|
||||
} else {
|
||||
GuarantorFundingDetails guarantorFundingDetails = guarantorForDelete.getGuarantorFundingDetail(guarantorFundingId);
|
||||
if (guarantorFundingDetails == null) { throw new GuarantorNotFoundException(loanId, guarantorForDelete.getId(),
|
||||
guarantorFundingId); }
|
||||
if (!guarantorFundingDetails.getStatus().isActive()) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode(GuarantorConstants.GUARANTOR_NOT_ACTIVE_ERROR);
|
||||
}
|
||||
GuarantorFundStatusType fundStatusType = GuarantorFundStatusType.DELETED;
|
||||
if (guarantorForDelete.getLoan().isDisbursed()) {
|
||||
if (guarantorForDelete.getLoan().isDisbursed() || guarantorForDelete.getLoan().isApproved()) {
|
||||
fundStatusType = GuarantorFundStatusType.WITHDRAWN;
|
||||
this.guarantorDomainService.releaseGuarantor(guarantorFundingDetails, LocalDate.now());
|
||||
}
|
||||
guarantorForDelete.updateStatus(guarantorFundingDetails, fundStatusType);
|
||||
|
||||
}
|
||||
this.guarantorRepository.save(guarantorForDelete);
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
this.guarantorRepository.saveAndFlush(guarantorForDelete);
|
||||
CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder()
|
||||
.withEntityId(guarantorForDelete.getId()).withLoanId(guarantorForDelete.getLoanId())
|
||||
.withOfficeId(guarantorForDelete.getOfficeId());
|
||||
@@ -244,7 +272,6 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
return commandProcessingResultBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
private void validateGuarantorBusinessRules(final Guarantor guarantor) {
|
||||
// validate guarantor conditions
|
||||
if (guarantor.isExistingCustomer()) {
|
||||
@@ -266,11 +293,20 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLoanStatus(Loan loan) {
|
||||
if (!loan.status().isActiveOrAwaitingApprovalOrDisbursal()) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.guarantor");
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("loan.is.closed");
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGuarantorDataIntegrityIssues(final DataIntegrityViolationException dve) {
|
||||
final Throwable realCause = dve.getMostSpecificCause();
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException("error.msg.guarantor.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource Guarantor: " + realCause.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class RecoverFromGuarantorCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final LoanWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public RecoverFromGuarantorCommandHandler(final LoanWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand command) {
|
||||
return this.writePlatformService.recoverFromGuarantor(command.getLoanId());
|
||||
}
|
||||
|
||||
}
|
||||
+9
-2
@@ -47,6 +47,8 @@ import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
|
||||
import org.mifosplatform.portfolio.collateral.domain.LoanCollateral;
|
||||
import org.mifosplatform.portfolio.collateral.service.CollateralAssembler;
|
||||
import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
|
||||
import org.mifosplatform.portfolio.common.service.BusinessEventNotifierService;
|
||||
import org.mifosplatform.portfolio.fund.domain.Fund;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
|
||||
@@ -128,6 +130,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
|
||||
private final LoanAccountDomainService loanAccountDomainService;
|
||||
private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
|
||||
@Autowired
|
||||
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
|
||||
@@ -144,7 +147,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
final SavingsAccountAssembler savingsAccountAssembler, final AccountAssociationsRepository accountAssociationsRepository,
|
||||
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
|
||||
final LoanReadPlatformService loanReadPlatformService, final LoanAccountDomainService loanAccountDomainService,
|
||||
final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository) {
|
||||
final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository,
|
||||
final BusinessEventNotifierService businessEventNotifierService) {
|
||||
this.context = context;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
|
||||
@@ -171,7 +175,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
this.loanReadPlatformService = loanReadPlatformService;
|
||||
this.loanAccountDomainService = loanAccountDomainService;
|
||||
this.accountNumberFormatRepository = accountNumberFormatRepository;
|
||||
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
}
|
||||
|
||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||
@@ -751,6 +755,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
changes.put("note", noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_APPROVED, loan);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -794,6 +800,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
final Note note = Note.loanNote(loan, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_UNDO_APPROVAL, loan);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
|
||||
+2
@@ -81,4 +81,6 @@ public interface LoanWritePlatformService {
|
||||
|
||||
void recalculateInterest();
|
||||
|
||||
CommandProcessingResult recoverFromGuarantor(Long loanId);
|
||||
|
||||
}
|
||||
+43
-9
@@ -92,7 +92,9 @@ import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDi
|
||||
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
|
||||
import org.mifosplatform.portfolio.collectionsheet.command.SingleDisbursalCommand;
|
||||
import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentCommand;
|
||||
import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
|
||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.common.service.BusinessEventNotifierService;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants;
|
||||
@@ -124,6 +126,7 @@ import org.mifosplatform.portfolio.loanaccount.exception.LoanDisbursalException;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.service.GuarantorDomainService;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
|
||||
@@ -193,6 +196,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper;
|
||||
private final AccountAssociationsRepository accountAssociationRepository;
|
||||
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final GuarantorDomainService guarantorDomainService;
|
||||
|
||||
@Autowired
|
||||
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -217,7 +222,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService,
|
||||
final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper,
|
||||
final AccountAssociationsRepository accountAssociationRepository,
|
||||
final AccountTransferDetailRepository accountTransferDetailRepository) {
|
||||
final AccountTransferDetailRepository accountTransferDetailRepository,
|
||||
final BusinessEventNotifierService businessEventNotifierService, final GuarantorDomainService guarantorDomainService) {
|
||||
this.context = context;
|
||||
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
|
||||
this.loanAssembler = loanAssembler;
|
||||
@@ -250,6 +256,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanApplicationCommandFromApiJsonHelper = loanApplicationCommandFromApiJsonHelper;
|
||||
this.accountAssociationRepository = accountAssociationRepository;
|
||||
this.accountTransferDetailRepository = accountTransferDetailRepository;
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
this.guarantorDomainService = guarantorDomainService;
|
||||
}
|
||||
|
||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||
@@ -383,10 +391,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final PortfolioAccountData savingAccountData = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId);
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loanId, "Loan Charge Payment",
|
||||
locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction);
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
|
||||
@@ -625,11 +635,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.retriveLoanLinkedAssociation(loan.getId());
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loan.getId(),
|
||||
"Loan Charge Payment", locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(),
|
||||
entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null,
|
||||
fromSavingsAccount, isRegularTransaction);
|
||||
fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
updateRecurringCalendarDatesForInterestRecalculation(loan);
|
||||
@@ -689,6 +700,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_UNDO_DISBURSAL, loan);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -899,6 +911,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
this.loanAccountDomainService.recalculateAccruals(loan);
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_UNDO_TRANSACTION, transactionToAdjust);
|
||||
if (newTransactionDetail.isRepayment() && newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT, newTransactionDetail);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
@@ -1083,6 +1099,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
this.loanAccountDomainService.recalculateAccruals(loan);
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_WRITTEN_OFF, writeoff);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(writeoff.getId()) //
|
||||
@@ -1643,10 +1660,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
|
||||
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
|
||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction);
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -1673,12 +1692,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
throw new LinkedAccountRequiredException("loan.disburse.to.savings", errorMessage, loan.getId());
|
||||
}
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final boolean isRegularTransaction = true;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount.getAmount(),
|
||||
PortfolioAccountType.LOAN, PortfolioAccountType.SAVINGS, loan.getId(), portfolioAccountData.accountId(),
|
||||
"Loan Disbursement", locale, fmt, paymentDetail, LoanTransactionType.DISBURSEMENT.getValue(), null, null, null,
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, txnExternalId, loan, null, fromSavingsAccount,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
|
||||
}
|
||||
@@ -1703,12 +1723,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.getLoanId());
|
||||
}
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(new LocalDate(),
|
||||
installmentChargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
|
||||
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null,
|
||||
null, LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
|
||||
installmentChargeData.getInstallmentNumber(), AccountTransferType.CHARGE_PAYMENT.getValue(), null,
|
||||
null, null, null, null, fromSavingsAccount, isRegularTransaction);
|
||||
null, null, null, null, fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferFeeCharge(sb, accountTransferDTO);
|
||||
}
|
||||
}
|
||||
@@ -1716,12 +1737,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService
|
||||
.retriveLoanLinkedAssociation(chargeData.getLoanId());
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(new LocalDate(),
|
||||
chargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
|
||||
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null,
|
||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), null,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferFeeCharge(sb, accountTransferDTO);
|
||||
}
|
||||
}
|
||||
@@ -2377,7 +2399,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LocalDate recalculateFrom = null;
|
||||
Long overdurPenaltyWaitPeriod = null;
|
||||
LocalDate lastTransactionDate = null;
|
||||
|
||||
LoanTransaction writeOffTransaction = loan.findWriteOffTransaction();
|
||||
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(),
|
||||
CalendarEntityType.LOAN_RECALCULATION_DETAIL.getValue());
|
||||
@@ -2412,6 +2434,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
this.loanAccountDomainService.recalculateAccruals(loan);
|
||||
if (writeOffTransaction != null) {
|
||||
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_UNDO_WRITTEN_OFF, writeOffTransaction);
|
||||
}
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
@@ -2543,10 +2568,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
|
||||
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
|
||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction);
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
|
||||
return transaction;
|
||||
@@ -2612,6 +2639,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanAccountDomainService.recalculateAccruals(loan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult recoverFromGuarantor(final Long loanId) {
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
this.guarantorDomainService.transaferFundsFromGuarantor(loan);
|
||||
return new CommandProcessingResultBuilder().withLoanId(loanId).build();
|
||||
}
|
||||
|
||||
private void updateLoanTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
|
||||
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
|
||||
if (transferTransaction != null) {
|
||||
|
||||
+10
-1
@@ -101,6 +101,7 @@ public class SavingsApiConstants {
|
||||
public static final String enforceMinRequiredBalanceParamName = "enforceMinRequiredBalance";
|
||||
public static final String minBalanceForInterestCalculationParamName = "minBalanceForInterestCalculation";
|
||||
public static final String withdrawBalanceParamName = "withdrawBalance";
|
||||
public static final String onHoldFundsParamName = "onHoldFunds";
|
||||
|
||||
// transaction parameters
|
||||
public static final String transactionDateParamName = "transactionDate";
|
||||
@@ -138,6 +139,11 @@ public class SavingsApiConstants {
|
||||
public static final String charges = "charges";
|
||||
public static final String linkedAccount = "linkedAccount";
|
||||
|
||||
// Savings on hold transaction
|
||||
public static final String onHoldTransactionTypeParamName = "transactionType";
|
||||
public static final String onHoldTransactionDateParamName = "transactionDate";
|
||||
public static final String onHoldReversedParamName = "reversed";
|
||||
|
||||
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
monthDayFormatParamName, nameParamName, shortNameParamName, descriptionParamName, currencyCodeParamName,
|
||||
digitsAfterDecimalParamName, inMultiplesOfParamName, nominalAnnualInterestRateParamName,
|
||||
@@ -195,7 +201,7 @@ public class SavingsApiConstants {
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName,
|
||||
feeOnMonthDayParamName, "summary", "transactions", "productOptions", "interestCompoundingPeriodTypeOptions",
|
||||
"interestPostingPeriodTypeOptions", "interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions",
|
||||
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee"));
|
||||
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee", onHoldFundsParamName));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName,
|
||||
@@ -224,4 +230,7 @@ public class SavingsApiConstants {
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_CHARGES_PAY_CHARGE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(
|
||||
amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_ON_HOLD_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName,
|
||||
amountParamName, onHoldTransactionTypeParamName, onHoldTransactionDateParamName, onHoldReversedParamName));
|
||||
}
|
||||
+5
-5
@@ -11,16 +11,16 @@ public class SavingsTransactionBooleanValues {
|
||||
private final boolean isRegularTransaction;
|
||||
private final boolean isApplyWithdrawFee;
|
||||
private final boolean isInterestTransfer;
|
||||
private final boolean isWithdrawBalance;
|
||||
private final boolean isExceptionForBalanceCheck;
|
||||
|
||||
public SavingsTransactionBooleanValues(final boolean isAccountTransfer, final boolean isRegularTransaction,
|
||||
final boolean isApplyWithdrawFee, final boolean isInterestTransfer, final boolean isWithdrawBalance) {
|
||||
final boolean isApplyWithdrawFee, final boolean isInterestTransfer, final boolean isExceptionForBalanceCheck) {
|
||||
|
||||
this.isAccountTransfer = isAccountTransfer;
|
||||
this.isRegularTransaction = isRegularTransaction;
|
||||
this.isApplyWithdrawFee = isApplyWithdrawFee;
|
||||
this.isInterestTransfer = isInterestTransfer;
|
||||
this.isWithdrawBalance = isWithdrawBalance;
|
||||
this.isExceptionForBalanceCheck = isExceptionForBalanceCheck;
|
||||
}
|
||||
|
||||
public boolean isAccountTransfer() {
|
||||
@@ -39,8 +39,8 @@ public class SavingsTransactionBooleanValues {
|
||||
return this.isInterestTransfer;
|
||||
}
|
||||
|
||||
public boolean isWithdrawBalance() {
|
||||
return this.isWithdrawBalance;
|
||||
public boolean isExceptionForBalanceCheck() {
|
||||
return this.isExceptionForBalanceCheck;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||
import org.mifosplatform.portfolio.savings.data.DepositAccountOnHoldTransactionData;
|
||||
import org.mifosplatform.portfolio.savings.service.DepositAccountOnHoldTransactionReadPlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/savingsaccounts/{savingsId}/onholdtransactions")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class DepositAccountOnHoldFundTransactionsApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<DepositAccountOnHoldTransactionData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final DepositAccountOnHoldTransactionReadPlatformService depositAccountOnHoldTransactionReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountOnHoldFundTransactionsApiResource(final PlatformSecurityContext context,
|
||||
final DefaultToApiJsonSerializer<DepositAccountOnHoldTransactionData> toApiJsonSerializer,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final DepositAccountOnHoldTransactionReadPlatformService depositAccountOnHoldTransactionReadPlatformService) {
|
||||
this.context = context;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.depositAccountOnHoldTransactionReadPlatformService = depositAccountOnHoldTransactionReadPlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveAll(@PathParam("savingsId") final Long savingsId,
|
||||
@QueryParam("guarantorFundingId") final Long guarantorFundingId, @Context final UriInfo uriInfo,
|
||||
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
|
||||
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
|
||||
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
|
||||
|
||||
final Page<DepositAccountOnHoldTransactionData> transfers = this.depositAccountOnHoldTransactionReadPlatformService.retriveAll(
|
||||
savingsId, guarantorFundingId, searchParameters);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer
|
||||
.serialize(settings, transfers, SavingsApiConstants.SAVINGS_ACCOUNT_ON_HOLD_RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
}
|
||||
+16
-8
@@ -50,6 +50,7 @@ public class SavingsAccountData {
|
||||
private final BigDecimal minRequiredBalance;
|
||||
private final boolean enforceMinRequiredBalance;
|
||||
private final BigDecimal minBalanceForInterestCalculation;
|
||||
private final BigDecimal onHoldFunds;
|
||||
|
||||
// associations
|
||||
private final SavingsAccountSummaryData summary;
|
||||
@@ -83,7 +84,8 @@ public class SavingsAccountData {
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
||||
final SavingsAccountSummaryData summary, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
||||
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance, final BigDecimal minBalanceForInterestCalculation) {
|
||||
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal onHoldFunds) {
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<StaffData> fieldOfficerOptions = null;
|
||||
@@ -105,7 +107,7 @@ public class SavingsAccountData {
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation);
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds);
|
||||
}
|
||||
|
||||
public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) {
|
||||
@@ -141,6 +143,7 @@ public class SavingsAccountData {
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -164,7 +167,7 @@ public class SavingsAccountData {
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation);
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds);
|
||||
}
|
||||
|
||||
public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo,
|
||||
@@ -198,6 +201,7 @@ public class SavingsAccountData {
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -221,7 +225,7 @@ public class SavingsAccountData {
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation);
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
||||
@@ -253,7 +257,8 @@ public class SavingsAccountData {
|
||||
template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions,
|
||||
template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions,
|
||||
template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.allowOverdraft, account.overdraftLimit,
|
||||
account.minRequiredBalance, account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation);
|
||||
account.minRequiredBalance, account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation,
|
||||
account.onHoldFunds);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||
@@ -275,7 +280,8 @@ public class SavingsAccountData {
|
||||
transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions, account.allowOverdraft, account.overdraftLimit,
|
||||
account.minRequiredBalance, account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation);
|
||||
account.minRequiredBalance, account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation,
|
||||
account.onHoldFunds);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -311,6 +317,7 @@ public class SavingsAccountData {
|
||||
final BigDecimal minRequiredBalance = null;
|
||||
final boolean enforceMinRequiredBalance = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -334,7 +341,7 @@ public class SavingsAccountData {
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation);
|
||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds);
|
||||
}
|
||||
|
||||
private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId,
|
||||
@@ -354,7 +361,7 @@ public class SavingsAccountData {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
||||
final Collection<SavingsAccountChargeData> charges, final Collection<ChargeData> chargeOptions, final boolean allowOverdraft,
|
||||
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||
final BigDecimal minBalanceForInterestCalculation) {
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal onHoldFunds) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.depositType = depositType;
|
||||
@@ -409,6 +416,7 @@ public class SavingsAccountData {
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||
this.onHoldFunds = onHoldFunds;
|
||||
}
|
||||
|
||||
private SavingsAccountChargeData getWithdrawalFee() {
|
||||
|
||||
+8
-7
@@ -176,11 +176,11 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final String transferDescription = command.stringValueOfParameterNamed(transferDescriptionParamName);
|
||||
final SavingsAccount toSavingsAccount = this.depositAccountAssembler.assembleFrom(toSavingsId,
|
||||
DepositAccountType.SAVINGS_DEPOSIT);
|
||||
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isAccountTransfer);
|
||||
isAccountTransfer, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} else {
|
||||
final SavingsAccountTransaction withdrawal = this.handleWithdrawal(account, fmt, closedDate, account.getAccountBalance(),
|
||||
@@ -254,11 +254,11 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final String transferDescription = command.stringValueOfParameterNamed(transferDescriptionParamName);
|
||||
final SavingsAccount toSavingsAccount = this.depositAccountAssembler.assembleFrom(toSavingsId,
|
||||
DepositAccountType.SAVINGS_DEPOSIT);
|
||||
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, transactionAmount,
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} else {
|
||||
final SavingsAccountTransaction withdrawal = this.handleWithdrawal(account, fmt, closedDate, account.getAccountBalance(),
|
||||
@@ -315,7 +315,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
DepositAccountOnClosureType closureType = DepositAccountOnClosureType.fromInt(closureTypeValue);
|
||||
|
||||
if (closureType.isTransferToSavings()) {
|
||||
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toSavingsAccountIdParamName);
|
||||
final String transferDescription = command.stringValueOfParameterNamed(transferDescriptionParamName);
|
||||
final SavingsAccount toSavingsAccount = this.depositAccountAssembler.assembleFrom(toSavingsId,
|
||||
@@ -323,7 +323,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} else {
|
||||
final SavingsAccountTransaction withdrawal = this.handleWithdrawal(account, fmt, closedDate, account.getAccountBalance(),
|
||||
@@ -371,6 +371,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
DepositAccountOnClosureType closureType = DepositAccountOnClosureType.fromInt(closureTypeValue);
|
||||
|
||||
if (closureType.isTransferToSavings()) {
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toSavingsAccountIdParamName);
|
||||
final String transferDescription = command.stringValueOfParameterNamed(transferDescriptionParamName);
|
||||
final SavingsAccount toSavingsAccount = this.depositAccountAssembler.assembleFrom(toSavingsId,
|
||||
@@ -378,7 +379,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} else {
|
||||
final SavingsAccountTransaction withdrawal = this.handleWithdrawal(account, fmt, closedDate, account.getAccountBalance(),
|
||||
|
||||
+59
-1
@@ -8,14 +8,21 @@ package org.mifosplatform.portfolio.savings.domain;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorFundingTransaction;
|
||||
import org.mifosplatform.portfolio.savings.DepositAccountOnHoldTransactionType;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@@ -36,8 +43,59 @@ public class DepositAccountOnHoldTransaction extends AbstractPersistable<Long> {
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
private Date transactionDate;
|
||||
|
||||
|
||||
@Column(name = "is_reversed", nullable = false)
|
||||
private boolean reversed;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "created_date", nullable = false)
|
||||
private Date createdDate;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "depositAccountOnHoldTransaction", optional = true, orphanRemoval = true)
|
||||
private GuarantorFundingTransaction guarantorFundingTransaction;
|
||||
|
||||
protected DepositAccountOnHoldTransaction() {}
|
||||
|
||||
private DepositAccountOnHoldTransaction(final SavingsAccount savingsAccount, final BigDecimal amount,
|
||||
final DepositAccountOnHoldTransactionType transactionType, final LocalDate transactionDate, final boolean reversed) {
|
||||
this.savingsAccount = savingsAccount;
|
||||
this.amount = amount;
|
||||
this.transactionType = transactionType.getValue();
|
||||
this.transactionDate = transactionDate.toDate();
|
||||
this.createdDate = new Date();
|
||||
this.reversed = reversed;
|
||||
}
|
||||
|
||||
public static DepositAccountOnHoldTransaction hold(final SavingsAccount savingsAccount, final BigDecimal amount,
|
||||
final LocalDate transactionDate) {
|
||||
boolean reversed = false;
|
||||
return new DepositAccountOnHoldTransaction(savingsAccount, amount, DepositAccountOnHoldTransactionType.HOLD, transactionDate,
|
||||
reversed);
|
||||
}
|
||||
|
||||
public static DepositAccountOnHoldTransaction release(final SavingsAccount savingsAccount, final BigDecimal amount,
|
||||
final LocalDate transactionDate) {
|
||||
boolean reversed = false;
|
||||
return new DepositAccountOnHoldTransaction(savingsAccount, amount, DepositAccountOnHoldTransactionType.RELEASE, transactionDate,
|
||||
reversed);
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public void reverseTransaction() {
|
||||
this.reversed = true;
|
||||
if (this.getTransactionType().isHold()) {
|
||||
this.savingsAccount.releaseFunds(this.amount);
|
||||
} else {
|
||||
this.savingsAccount.holdFunds(this.amount);
|
||||
}
|
||||
}
|
||||
|
||||
public DepositAccountOnHoldTransactionType getTransactionType() {
|
||||
return DepositAccountOnHoldTransactionType.fromInt(this.transactionType);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
|
||||
public interface DepositAccountOnHoldTransactionRepository extends JpaRepository<DepositAccountOnHoldTransaction ,Long>,
|
||||
JpaSpecificationExecutor<DepositAccountOnHoldTransaction>{
|
||||
|
||||
}
|
||||
+18
-2
@@ -858,7 +858,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return transactionBeforeLastInterestPosting;
|
||||
}
|
||||
|
||||
public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transactionAmount, final boolean isWithdrawBalance) {
|
||||
public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transactionAmount, final boolean isException) {
|
||||
final List<SavingsAccountTransaction> transactionsSortedByDate = retreiveListOfTransactions();
|
||||
Money runningBalance = Money.zero(this.currency);
|
||||
Money minRequiredBalance = minRequiredBalanceDerived(getCurrency());
|
||||
@@ -874,7 +874,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final BigDecimal withdrawalFee = null;
|
||||
// deal with potential minRequiredBalance and
|
||||
// enforceMinRequiredBalance
|
||||
if (!isWithdrawBalance && transaction.canProcessBalanceCheck()) {
|
||||
if (!isException && transaction.canProcessBalanceCheck()) {
|
||||
if (runningBalance.minus(minRequiredBalance).isLessThanZero()) { throw new InsufficientAccountBalanceException(
|
||||
"transactionAmount", getAccountBalance(), withdrawalFee, transactionAmount); }
|
||||
}
|
||||
@@ -2445,4 +2445,20 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
return minReqBalance;
|
||||
}
|
||||
|
||||
public BigDecimal getOnHoldFunds() {
|
||||
return this.onHoldFunds == null ? BigDecimal.ZERO : this.onHoldFunds;
|
||||
}
|
||||
|
||||
public void holdFunds(BigDecimal onHoldFunds) {
|
||||
this.onHoldFunds = getOnHoldFunds().add(onHoldFunds);
|
||||
}
|
||||
|
||||
public void releaseFunds(BigDecimal onHoldFunds) {
|
||||
this.onHoldFunds = getOnHoldFunds().subtract(onHoldFunds);
|
||||
}
|
||||
|
||||
public BigDecimal getWithdrawableBalance() {
|
||||
return getAccountBalance().subtract(minRequiredBalanceDerived(getCurrency()).getAmount());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -84,7 +84,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
account.calculateInterestUsing(mc, today, transactionBooleanValues.isInterestTransfer(),
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(transactionAmount, transactionBooleanValues.isWithdrawBalance());
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(transactionAmount, transactionBooleanValues.isExceptionForBalanceCheck());
|
||||
saveTransactionToGenerateTransactionId(withdrawal);
|
||||
this.savingsAccountRepository.save(account);
|
||||
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.mifosplatform.portfolio.savings.data.DepositAccountOnHoldTransactionData;
|
||||
|
||||
public interface DepositAccountOnHoldTransactionReadPlatformService {
|
||||
|
||||
public Page<DepositAccountOnHoldTransactionData> retriveAll(final Long savingsId, final Long guarantorFundingId,
|
||||
final SearchParameters searchParameters);
|
||||
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.mifosplatform.portfolio.savings.data.DepositAccountOnHoldTransactionData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DepositAccountOnHoldTransactionReadPlatformServiceImpl implements DepositAccountOnHoldTransactionReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PaginationHelper<DepositAccountOnHoldTransactionData> paginationHelper = new PaginationHelper<>();
|
||||
private final DepositAccountOnHoldTransactionsMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountOnHoldTransactionReadPlatformServiceImpl(final RoutingDataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
mapper = new DepositAccountOnHoldTransactionsMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DepositAccountOnHoldTransactionData> retriveAll(Long savingsId, Long guarantorFundingId, SearchParameters searchParameters) {
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
List<Long> paramObj = new ArrayList<>(2);
|
||||
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
|
||||
sqlBuilder.append(this.mapper.schema());
|
||||
|
||||
sqlBuilder.append(" where tr.savings_account_id = ? ");
|
||||
paramObj.add(savingsId);
|
||||
if (guarantorFundingId != null) {
|
||||
sqlBuilder.append(" and gt.guarantor_fund_detail_id = ? ");
|
||||
paramObj.add(guarantorFundingId);
|
||||
}
|
||||
|
||||
if (searchParameters.isOrderByRequested()) {
|
||||
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
||||
|
||||
if (searchParameters.isSortOrderProvided()) {
|
||||
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
|
||||
}
|
||||
}
|
||||
|
||||
if (searchParameters.isLimited()) {
|
||||
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
|
||||
if (searchParameters.isOffset()) {
|
||||
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
final String sqlCountRows = "SELECT FOUND_ROWS()";
|
||||
final Object[] finalObjectArray = paramObj.toArray();
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray, this.mapper);
|
||||
|
||||
}
|
||||
|
||||
private static final class DepositAccountOnHoldTransactionsMapper implements RowMapper<DepositAccountOnHoldTransactionData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
public DepositAccountOnHoldTransactionsMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("tr.id as transactionId, tr.transaction_type_enum as transactionType, ");
|
||||
sqlBuilder.append("tr.transaction_date as transactionDate, tr.amount as transactionAmount,");
|
||||
sqlBuilder.append("tr.is_reversed as reversed ");
|
||||
sqlBuilder.append("from m_deposit_account_on_hold_transaction tr ");
|
||||
sqlBuilder.append(" left join m_guarantor_transaction gt on gt.deposit_on_hold_transaction_id = tr.id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DepositAccountOnHoldTransactionData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
|
||||
throws SQLException {
|
||||
final Long id = rs.getLong("transactionId");
|
||||
final int transactionTypeInt = JdbcSupport.getInteger(rs, "transactionType");
|
||||
final EnumOptionData transactionType = SavingsEnumerations.onHoldTransactionType(transactionTypeInt);
|
||||
|
||||
final LocalDate date = JdbcSupport.getLocalDate(rs, "transactionDate");
|
||||
final BigDecimal amount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transactionAmount");
|
||||
final boolean reversed = rs.getBoolean("reversed");
|
||||
return DepositAccountOnHoldTransactionData.instance(id, amount, transactionType, date, reversed);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
-5
@@ -350,8 +350,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
final Collection<SavingsAccountChargeData> charges = fromChargesToSavingsCharges(productCharges);
|
||||
|
||||
final boolean feeChargesOnly = false;
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService
|
||||
.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
|
||||
Collection<StaffData> fieldOfficerOptions = null;
|
||||
|
||||
@@ -427,8 +426,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
final Collection<SavingsAccountChargeData> charges = null;
|
||||
|
||||
final boolean feeChargesOnly = true;
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService
|
||||
.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
|
||||
if (depositAccountType.isFixedDeposit()) {
|
||||
|
||||
@@ -1398,10 +1396,12 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
final Long toAccountId = rs.getLong("toAcc");
|
||||
final BigDecimal transactionAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "amount");
|
||||
final boolean isRegularTransaction = false;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final LocalDate transactionDate = JdbcSupport.getLocalDate(rs, "transactionDate");
|
||||
return new AccountTransferDTO(transactionDate, transactionAmount, PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
|
||||
fromAccountId, toAccountId, "trasfer interest to savings", null, null, null, null, null, null, null,
|
||||
AccountTransferType.INTEREST_TRANSFER.getValue(), null, null, null, null, null, null, isRegularTransaction);
|
||||
AccountTransferType.INTEREST_TRANSFER.getValue(), null, null, null, null, null, null, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -205,11 +205,12 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
} else {
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
boolean isRegularTransaction = false;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(),
|
||||
amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
|
||||
portfolioAccountData.accountId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null,
|
||||
null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, account, fromSavingsAccount,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
final boolean isInterestTransfer = false;
|
||||
@@ -279,12 +280,13 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
this.depositAccountDomainService.handleRDDeposit(account, fmt, account.getActivationLocalDate(),
|
||||
amountForDeposit.getAmount(), null, isRegularTransaction);
|
||||
} else {
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(),
|
||||
amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
|
||||
portfolioAccountData.accountId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null,
|
||||
null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, account, fromSavingsAccount,
|
||||
isRegularTransaction);
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
+11
-8
@@ -252,7 +252,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.total_penalty_charge_derived as totalPenaltyCharge, ");
|
||||
sqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
||||
sqlBuilder.append("sa.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("sa.enforce_min_required_balance as enforceMinRequiredBalance ");
|
||||
sqlBuilder.append("sa.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("sa.on_hold_funds_derived as onHoldFunds ");
|
||||
sqlBuilder.append("from m_savings_account sa ");
|
||||
sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||
@@ -414,6 +415,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final BigDecimal totalPenaltyCharge = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalPenaltyCharge");
|
||||
final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
|
||||
"minBalanceForInterestCalculation");
|
||||
final BigDecimal onHoldFunds = rs.getBigDecimal("onHoldFunds");
|
||||
|
||||
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
|
||||
totalWithdrawalFees, totalAnnualFees, totalInterestEarned, totalInterestPosted, accountBalance, totalFeeCharge,
|
||||
@@ -423,7 +425,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary,
|
||||
allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation);
|
||||
allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
|
||||
onHoldFunds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,8 +520,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final Collection<SavingsAccountChargeData> charges = fromChargesToSavingsCharges(productCharges);
|
||||
|
||||
final boolean feeChargesOnly = false;
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService
|
||||
.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
|
||||
Collection<StaffData> fieldOfficerOptions = null;
|
||||
|
||||
@@ -576,8 +578,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final Collection<SavingsAccountChargeData> charges = null;
|
||||
|
||||
final boolean feeChargesOnly = true;
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService
|
||||
.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveSavingsApplicableCharges(feeChargesOnly);
|
||||
|
||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, fieldOfficerOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
@@ -743,7 +744,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
}
|
||||
|
||||
return SavingsAccountTransactionData.create(id, transactionType, paymentDetailData, savingsId, accountNo, date, currency,
|
||||
amount, runningBalance, reversed, transfer,submittedOnDate);
|
||||
amount, runningBalance, reversed, transfer, submittedOnDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,6 +928,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final SavingsAccountStatusEnumData status = null;
|
||||
// final LocalDate annualFeeNextDueDate = null;
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
|
||||
final SavingsAccountApplicationTimelineData timeline = SavingsAccountApplicationTimelineData.templateDefault();
|
||||
final EnumOptionData depositType = null;
|
||||
@@ -934,7 +936,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary,
|
||||
allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation);
|
||||
allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
|
||||
onHoldFunds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
ALTER TABLE `m_deposit_account_on_hold_transaction`
|
||||
ADD COLUMN `created_date` DATETIME NOT NULL;
|
||||
|
||||
ALTER TABLE `m_guarantor_transaction`
|
||||
ALTER `loan_transaction_id` DROP DEFAULT;
|
||||
|
||||
ALTER TABLE `m_guarantor_transaction`
|
||||
CHANGE COLUMN `loan_transaction_id` `loan_transaction_id` BIGINT(20) NULL ;
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'RECOVERGUARANTEES_LOAN', 'LOAN', 'RECOVERGUARANTEES', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'RECOVERGUARANTEES_LOAN_CHECKER', 'LOAN', 'RECOVERGUARANTEES_CHECKER', 0);
|
||||
ALTER TABLE `m_loan`
|
||||
DROP COLUMN `guarantee_outstanding_amount_derived`;
|
||||
|
||||
Reference in New Issue
Block a user