support repayment strategy approach for deciding how loan transactions should be processed against the loan schedule.
This commit is contained in:
+5
@@ -18,6 +18,11 @@ ADD COLUMN `loan_transaction_strategy_id` bigint(20) DEFAULT NULL,
|
|||||||
ADD KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
ADD KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||||
ADD CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`);
|
ADD CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`);
|
||||||
|
|
||||||
|
ALTER TABLE `portfolio_loan`
|
||||||
|
ADD COLUMN `loan_transaction_strategy_id` bigint(20) DEFAULT NULL,
|
||||||
|
ADD KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||||
|
ADD CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`);
|
||||||
|
|
||||||
-- update ref table with out-of-the-box strategies
|
-- update ref table with out-of-the-box strategies
|
||||||
|
|
||||||
INSERT INTO `ref_loan_transaction_processing_strategy`
|
INSERT INTO `ref_loan_transaction_processing_strategy`
|
||||||
|
|||||||
+8
-1
@@ -15,6 +15,7 @@ public class SubmitLoanApplicationCommand {
|
|||||||
private final String externalId;
|
private final String externalId;
|
||||||
|
|
||||||
private final Long fundId;
|
private final Long fundId;
|
||||||
|
private final Long transactionProcessingStrategyId;
|
||||||
|
|
||||||
private final BigDecimal principal;
|
private final BigDecimal principal;
|
||||||
private final BigDecimal inArrearsTolerance;
|
private final BigDecimal inArrearsTolerance;
|
||||||
@@ -39,7 +40,8 @@ public class SubmitLoanApplicationCommand {
|
|||||||
private LoanSchedule loanSchedule;
|
private LoanSchedule loanSchedule;
|
||||||
|
|
||||||
public SubmitLoanApplicationCommand(
|
public SubmitLoanApplicationCommand(
|
||||||
final Long clientId, final Long productId, final String externalId, final Long fundId,
|
final Long clientId, final Long productId, final String externalId,
|
||||||
|
final Long fundId, final Long transactionProcessingStrategyId,
|
||||||
final LocalDate submittedOnDate, final String submittedOnNote,
|
final LocalDate submittedOnDate, final String submittedOnNote,
|
||||||
final LocalDate expectedDisbursementDate,
|
final LocalDate expectedDisbursementDate,
|
||||||
final LocalDate repaymentsStartingFromDate,
|
final LocalDate repaymentsStartingFromDate,
|
||||||
@@ -55,6 +57,7 @@ public class SubmitLoanApplicationCommand {
|
|||||||
this.productId = productId;
|
this.productId = productId;
|
||||||
this.externalId = externalId;
|
this.externalId = externalId;
|
||||||
this.fundId = fundId;
|
this.fundId = fundId;
|
||||||
|
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
|
||||||
|
|
||||||
this.submittedOnDate = submittedOnDate;
|
this.submittedOnDate = submittedOnDate;
|
||||||
this.submittedOnNote = submittedOnNote;
|
this.submittedOnNote = submittedOnNote;
|
||||||
@@ -105,6 +108,10 @@ public class SubmitLoanApplicationCommand {
|
|||||||
return fundId;
|
return fundId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getTransactionProcessingStrategyId() {
|
||||||
|
return transactionProcessingStrategyId;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getPrincipal() {
|
public BigDecimal getPrincipal() {
|
||||||
return principal;
|
return principal;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -872,7 +872,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||||
|
|
||||||
Set<String> supportedParams = new HashSet<String>(
|
Set<String> supportedParams = new HashSet<String>(
|
||||||
Arrays.asList("clientId", "productId", "externalId", "fundId",
|
Arrays.asList("clientId", "productId", "externalId", "fundId", "transactionProcessingStrategyId",
|
||||||
"principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments",
|
"principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments",
|
||||||
"repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
|
"repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||||
"expectedDisbursementDate", "repaymentsStartingFromDate", "interestChargedFromDate", "submittedOnDate", "submittedOnNote",
|
"expectedDisbursementDate", "repaymentsStartingFromDate", "interestChargedFromDate", "submittedOnDate", "submittedOnNote",
|
||||||
@@ -886,6 +886,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
Long clientId = extractLongParameter("clientId", requestMap, modifiedParameters);
|
Long clientId = extractLongParameter("clientId", requestMap, modifiedParameters);
|
||||||
Long productId = extractLongParameter("productId", requestMap, modifiedParameters);
|
Long productId = extractLongParameter("productId", requestMap, modifiedParameters);
|
||||||
Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters);
|
Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters);
|
||||||
|
Long transactionProcessingStrategyId = extractLongParameter("transactionProcessingStrategyId", requestMap, modifiedParameters);
|
||||||
String externalId = extractStringParameter("externalId", requestMap, modifiedParameters);
|
String externalId = extractStringParameter("externalId", requestMap, modifiedParameters);
|
||||||
|
|
||||||
BigDecimal principal = extractBigDecimalParameter("principal", requestMap, modifiedParameters);
|
BigDecimal principal = extractBigDecimalParameter("principal", requestMap, modifiedParameters);
|
||||||
@@ -908,7 +909,8 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
|
|
||||||
String submittedOnNote = extractStringParameter("submittedOnNote", requestMap, modifiedParameters);
|
String submittedOnNote = extractStringParameter("submittedOnNote", requestMap, modifiedParameters);
|
||||||
|
|
||||||
return new SubmitLoanApplicationCommand(clientId, productId, externalId, fundId, submittedOnDate, submittedOnNote,
|
return new SubmitLoanApplicationCommand(clientId, productId, externalId, fundId, transactionProcessingStrategyId,
|
||||||
|
submittedOnDate, submittedOnNote,
|
||||||
expectedDisbursementDate, repaymentsStartingFromDate, interestChargedFromDate,
|
expectedDisbursementDate, repaymentsStartingFromDate, interestChargedFromDate,
|
||||||
principal, interestRatePerPeriod, interestRateFrequencyTypeValue, interestTypeValue, interestCalculationPeriodTypeValue,
|
principal, interestRatePerPeriod, interestRateFrequencyTypeValue, interestTypeValue, interestCalculationPeriodTypeValue,
|
||||||
repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationTypeValue, inArrearsToleranceValue);
|
repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationTypeValue, inArrearsToleranceValue);
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@JoinColumn(name = "fund_id", nullable = true)
|
@JoinColumn(name = "fund_id", nullable = true)
|
||||||
private Fund fund;
|
private Fund fund;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
||||||
|
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||||
|
|
||||||
@Column(name = "external_id")
|
@Column(name = "external_id")
|
||||||
private String externalId;
|
private String externalId;
|
||||||
|
|
||||||
@@ -136,11 +140,10 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@Transient
|
@Transient
|
||||||
private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessor = new LoanRepaymentScheduleTransactionProcessorFactory();
|
private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessor = new LoanRepaymentScheduleTransactionProcessorFactory();
|
||||||
|
|
||||||
public static Loan createNew(final Fund fund,
|
public static Loan createNew(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||||
final LoanProduct loanProduct, final Client client,
|
final LoanProduct loanProduct, final Client client,
|
||||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail) {
|
final LoanProductRelatedDetail loanRepaymentScheduleDetail) {
|
||||||
return new Loan(client, fund, loanProduct, loanRepaymentScheduleDetail,
|
return new Loan(client, fund, transactionProcessingStrategy, loanProduct, loanRepaymentScheduleDetail, null);
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Loan() {
|
public Loan() {
|
||||||
@@ -149,15 +152,12 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.loanRepaymentScheduleDetail = null;
|
this.loanRepaymentScheduleDetail = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Loan(final Client client, Fund fund, final LoanProduct loanProduct,
|
public Loan(final Client client, Fund fund, LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProduct loanProduct,
|
||||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail,
|
final LoanProductRelatedDetail loanRepaymentScheduleDetail,
|
||||||
final LoanStatus loanStatus) {
|
final LoanStatus loanStatus) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
if (fund != null) {
|
this.fund = fund;
|
||||||
this.fund = fund;
|
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||||
} else {
|
|
||||||
this.fund = loanProduct.getFund();
|
|
||||||
}
|
|
||||||
this.loanProduct = loanProduct;
|
this.loanProduct = loanProduct;
|
||||||
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
|
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
|
||||||
this.loanStatus = loanStatus;
|
this.loanStatus = loanStatus;
|
||||||
@@ -445,7 +445,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
Collections.sort(repaymentsOrWaivers, transactionComparator);
|
Collections.sort(repaymentsOrWaivers, transactionComparator);
|
||||||
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor();
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy);
|
||||||
if (isTransactionChronologicallyLatest && !adjusted) {
|
if (isTransactionChronologicallyLatest && !adjusted) {
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments);
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+18
-7
@@ -1,21 +1,32 @@
|
|||||||
package org.mifosng.platform.loan.domain;
|
package org.mifosng.platform.loan.domain;
|
||||||
|
|
||||||
import org.mifosng.platform.infrastructure.MifosPlatformTenant;
|
|
||||||
import org.mifosng.platform.infrastructure.ThreadLocalContextUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class LoanRepaymentScheduleTransactionProcessorFactory {
|
public class LoanRepaymentScheduleTransactionProcessorFactory {
|
||||||
|
|
||||||
public LoanRepaymentScheduleTransactionProcessor determineProcessor() {
|
public LoanRepaymentScheduleTransactionProcessor determineProcessor(final LoanTransactionProcessingStrategy transactionProcessingStrategy) {
|
||||||
|
|
||||||
LoanRepaymentScheduleTransactionProcessor processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
|
LoanRepaymentScheduleTransactionProcessor processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
|
||||||
|
|
||||||
// FIXME - Just temp way of deciding what 'repayment strategy' to use for now.
|
if (transactionProcessingStrategy != null) {
|
||||||
MifosPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
|
|
||||||
if ("mifostenant-creocore".equalsIgnoreCase(tenant.getSchemaName())) {
|
if (transactionProcessingStrategy.isStandardMifosStrategy()) {
|
||||||
processor = new CreocoreLoanRepaymentScheduleTransactionProcessor();
|
processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionProcessingStrategy.isHeavensfamilyStrategy()) {
|
||||||
|
processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionProcessingStrategy.isCreocoreStrategy()) {
|
||||||
|
processor = new CreocoreLoanRepaymentScheduleTransactionProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionProcessingStrategy.isIndianRBIStrategy()) {
|
||||||
|
processor = new AdhikarLoanRepaymentScheduleTransactionProcessor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return processor;
|
return processor;
|
||||||
|
|||||||
+16
-4
@@ -25,11 +25,23 @@ public class LoanTransactionProcessingStrategy extends AbstractAuditableCustom<A
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
public String code() {
|
|
||||||
return this.code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransactionProcessingStrategyData toData() {
|
public TransactionProcessingStrategyData toData() {
|
||||||
return new TransactionProcessingStrategyData(this.getId(), this.code, this.name);
|
return new TransactionProcessingStrategyData(this.getId(), this.code, this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isStandardMifosStrategy() {
|
||||||
|
return "mifos-standard-strategy".equalsIgnoreCase(this.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHeavensfamilyStrategy() {
|
||||||
|
return "heavensfamily-strategy".equalsIgnoreCase(this.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCreocoreStrategy() {
|
||||||
|
return "creocore-strategy".equalsIgnoreCase(this.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIndianRBIStrategy() {
|
||||||
|
return "rbi-india-strategy".equalsIgnoreCase(this.code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+22
-3
@@ -13,6 +13,7 @@ import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
|||||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||||
import org.mifosng.platform.exceptions.FundNotFoundException;
|
import org.mifosng.platform.exceptions.FundNotFoundException;
|
||||||
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
|
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
|
||||||
|
import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException;
|
||||||
import org.mifosng.platform.fund.domain.Fund;
|
import org.mifosng.platform.fund.domain.Fund;
|
||||||
import org.mifosng.platform.fund.domain.FundRepository;
|
import org.mifosng.platform.fund.domain.FundRepository;
|
||||||
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
||||||
@@ -27,6 +28,8 @@ import org.mifosng.platform.loan.domain.LoanProductRepository;
|
|||||||
import org.mifosng.platform.loan.domain.LoanRepaymentScheduleInstallment;
|
import org.mifosng.platform.loan.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.mifosng.platform.loan.domain.LoanStatus;
|
import org.mifosng.platform.loan.domain.LoanStatus;
|
||||||
import org.mifosng.platform.loan.domain.LoanStatusRepository;
|
import org.mifosng.platform.loan.domain.LoanStatusRepository;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategy;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategyRepository;
|
||||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||||
import org.mifosng.platform.loanschedule.domain.AprCalculator;
|
import org.mifosng.platform.loanschedule.domain.AprCalculator;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -40,18 +43,22 @@ public class LoanAssembler {
|
|||||||
private final ClientRepository clientRepository;
|
private final ClientRepository clientRepository;
|
||||||
private final AprCalculator aprCalculator = new AprCalculator();
|
private final AprCalculator aprCalculator = new AprCalculator();
|
||||||
private final FundRepository fundRepository;
|
private final FundRepository fundRepository;
|
||||||
|
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public LoanAssembler(final LoanStatusRepository loanStatusRepository,
|
public LoanAssembler(final LoanStatusRepository loanStatusRepository,
|
||||||
final LoanProductRepository loanProductRepository,
|
final LoanProductRepository loanProductRepository,
|
||||||
final ClientRepository clientRepository, final FundRepository fundRepository) {
|
final ClientRepository clientRepository,
|
||||||
|
final FundRepository fundRepository,
|
||||||
|
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository) {
|
||||||
this.loanStatusRepository = loanStatusRepository;
|
this.loanStatusRepository = loanStatusRepository;
|
||||||
this.loanProductRepository = loanProductRepository;
|
this.loanProductRepository = loanProductRepository;
|
||||||
this.clientRepository = clientRepository;
|
this.clientRepository = clientRepository;
|
||||||
this.fundRepository = fundRepository;
|
this.fundRepository = fundRepository;
|
||||||
|
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Loan assembleFrom(SubmitLoanApplicationCommand command) {
|
public Loan assembleFrom(final SubmitLoanApplicationCommand command) {
|
||||||
|
|
||||||
LoanProduct loanProduct = this.loanProductRepository.findOne(command.getProductId());
|
LoanProduct loanProduct = this.loanProductRepository.findOne(command.getProductId());
|
||||||
if (loanProduct == null) {
|
if (loanProduct == null) {
|
||||||
@@ -87,8 +94,9 @@ public class LoanAssembler {
|
|||||||
|
|
||||||
// associating fund with loan product at creation is optional for now.
|
// associating fund with loan product at creation is optional for now.
|
||||||
Fund fund = findFundByIdIfProvided(command.getFundId());
|
Fund fund = findFundByIdIfProvided(command.getFundId());
|
||||||
|
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
|
||||||
|
|
||||||
Loan loan = Loan.createNew(fund, loanProduct, client, loanRepaymentScheduleDetail);
|
Loan loan = Loan.createNew(fund, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail);
|
||||||
loan.setExternalId(command.getExternalId());
|
loan.setExternalId(command.getExternalId());
|
||||||
|
|
||||||
for (ScheduledLoanInstallment scheduledLoanInstallment : loanRepaymentSchedule) {
|
for (ScheduledLoanInstallment scheduledLoanInstallment : loanRepaymentSchedule) {
|
||||||
@@ -125,4 +133,15 @@ public class LoanAssembler {
|
|||||||
}
|
}
|
||||||
return fund;
|
return fund;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
|
||||||
|
LoanTransactionProcessingStrategy strategy = null;
|
||||||
|
if (transactionProcessingStrategyId != null) {
|
||||||
|
strategy = this.loanTransactionProcessingStrategyRepository.findOne(transactionProcessingStrategyId);
|
||||||
|
if (strategy == null) {
|
||||||
|
throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -85,14 +85,14 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
|
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
|
||||||
LoanTransactionProcessingStrategy fund = null;
|
LoanTransactionProcessingStrategy strategy = null;
|
||||||
if (transactionProcessingStrategyId != null) {
|
if (transactionProcessingStrategyId != null) {
|
||||||
fund = this.loanTransactionProcessingStrategyRepository.findOne(transactionProcessingStrategyId);
|
strategy = this.loanTransactionProcessingStrategyRepository.findOne(transactionProcessingStrategyId);
|
||||||
if (fund == null) {
|
if (strategy == null) {
|
||||||
throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId);
|
throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fund;
|
return strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Fund findFundByIdIfProvided(final Long fundId) {
|
private Fund findFundByIdIfProvided(final Long fundId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user