diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepository.java index 955d6a210..a084795b4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepository.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepository.java @@ -46,6 +46,12 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat public static final String FIND_CLIENT_LOANS_TO_UPDATE_LOANPRODUCT_COUNTER = "from Loan l where l.loanProductCounter > :loanProductCounter" + " and l.client.id = :clientId and l.loanCounter is NULL order by l.loanProductCounter"; + public static final String FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_CLIENT = "Select loan.loanProduct.id from Loan loan where " + + "loan.client.id = :clientId and loan.loanStatus = :loanStatus group by loan.loanProduct.id"; + + public static final String FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP = "Select loan.loanProduct.id from Loan loan where " + + "loan.group.id = :groupId and loan.loanStatus = :loanStatus and loan.client.id is NULL group by loan.loanProduct.id"; + @Query(FIND_GROUP_LOANS_DISBURSED_AFTER) List getGroupLoansDisbursedAfter(@Param("disbursementDate") Date disbursementDate, @Param("groupId") Long groupId, @Param("loanType") Integer loanType); @@ -100,4 +106,10 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query("from Loan loan where loan.group.office.id IN :officeIds and loan.loanStatus IN :loanStatuses") List findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection officeIds, @Param("loanStatuses") Collection loanStatuses); + @Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_CLIENT) + List findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus); + + @Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP) + List findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/exception/LoanDisbursalException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/exception/LoanDisbursalException.java new file mode 100644 index 000000000..4f7d6fd25 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/exception/LoanDisbursalException.java @@ -0,0 +1,12 @@ +package org.mifosplatform.portfolio.loanaccount.exception; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +public class LoanDisbursalException extends AbstractPlatformDomainRuleException { + + public LoanDisbursalException(final String cureentProduct, final String restrictedProduct) { + super("error.msg.loan.disbursal.failed", "This loan could not be disbursed as `" + cureentProduct + "` and `" + restrictedProduct + + "` are not allowed to co-exist", new Object[] { cureentProduct, restrictedProduct }); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index a06543cee..0376b2258 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -32,8 +32,8 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.organisation.staff.domain.Staff; -import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; import org.mifosplatform.organisation.workingdays.domain.WorkingDays; +import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; import org.mifosplatform.portfolio.calendar.domain.Calendar; import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType; import org.mifosplatform.portfolio.calendar.domain.CalendarInstance; @@ -66,6 +66,7 @@ import org.mifosplatform.portfolio.loanaccount.domain.LoanSummaryWrapper; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository; import org.mifosplatform.portfolio.loanaccount.domain.LoanType; +import org.mifosplatform.portfolio.loanaccount.exception.LoanDisbursalException; import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException; import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException; import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException; @@ -73,8 +74,10 @@ import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFound import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanaccount.serialization.LoanEventApiJsonValidator; import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer; +import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail; import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException; +import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformService; import org.mifosplatform.portfolio.note.domain.Note; import org.mifosplatform.portfolio.note.domain.NoteRepository; import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; @@ -83,6 +86,7 @@ import org.mifosplatform.useradministration.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; @Service public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatformService { @@ -106,6 +110,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final HolidayRepository holidayRepository; private final ConfigurationDomainService configurationDomainService; private final WorkingDaysRepositoryWrapper workingDaysRepository; + private final LoanProductReadPlatformService loanProductReadPlatformService; @Autowired public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -118,7 +123,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, final LoanScheduleGeneratorFactory loanScheduleFactory, final CalendarInstanceRepository calendarInstanceRepository, final PaymentDetailWritePlatformService paymentDetailWritePlatformService, final HolidayRepository holidayRepository, - final ConfigurationDomainService configurationDomainService, final WorkingDaysRepositoryWrapper workingDaysRepository) { + final ConfigurationDomainService configurationDomainService, final WorkingDaysRepositoryWrapper workingDaysRepository, + final LoanProductReadPlatformService loanProductReadPlatformService) { this.context = context; this.loanEventApiJsonValidator = loanEventApiJsonValidator; @@ -139,6 +145,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.holidayRepository = holidayRepository; this.configurationDomainService = configurationDomainService; this.workingDaysRepository = workingDaysRepository; + this.loanProductReadPlatformService = loanProductReadPlatformService; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -155,6 +162,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.loanEventApiJsonValidator.validateDisbursement(command.json()); final Loan loan = retrieveLoanBy(loanId); + + //check for product mix validations + checkForProductMixRestrictions(loan); + // validate actual disbursement date against meeting date final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByLoanId(loan.getId(), CalendarEntityType.LOANS.getValue()); @@ -1233,4 +1244,31 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } this.holidayRepository.save(holidays); } + + private void checkForProductMixRestrictions(final Loan loan) { + + final List activeLoansLoanProductIds; + final Long productId = loan.loanProduct().getId(); + + if (loan.isGroupLoan()) { + activeLoansLoanProductIds = this.loanRepository.findActiveLoansLoanProductIdsByGroup(loan.getGroupId(), + LoanStatus.ACTIVE.getValue()); + } else { + activeLoansLoanProductIds = this.loanRepository.findActiveLoansLoanProductIdsByClient(loan.getClientId(), + LoanStatus.ACTIVE.getValue()); + } + checkForProductMixRestrictions(activeLoansLoanProductIds, productId, loan.loanProduct().productName()); + } + + private void checkForProductMixRestrictions(final List activeLoansLoanProductIds, final Long productId, final String productName) { + + if (!CollectionUtils.isEmpty(activeLoansLoanProductIds)) { + final Collection restrictedPrdouctsList = this.loanProductReadPlatformService + .retrieveRestrictedProductsForMix(productId); + for (LoanProductData restrictedProduct : restrictedPrdouctsList) { + if (activeLoansLoanProductIds.contains(restrictedProduct.getId())) { throw new LoanDisbursalException(productName, + restrictedProduct.getName()); } + } + } + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java index 9b007ebfd..2d4164b1e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java @@ -408,5 +408,9 @@ public class LoanProduct extends AbstractPersistable { } return closeLocalDate; } + + public String productName() { + return this.name; + } } \ No newline at end of file