/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.clientportfolio.loan.ui; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.mifos.application.admin.servicefacade.AdminServiceFacade; import org.mifos.application.servicefacade.LoanAccountServiceFacade; import org.mifos.clientportfolio.loan.service.CreateLoanSchedule; import org.mifos.clientportfolio.loan.service.RecurringSchedule; import org.mifos.clientportfolio.loan.ui.helper.LoanControllerHelper; import org.mifos.clientportfolio.newloan.applicationservice.CreateGlimLoanAccount; import org.mifos.clientportfolio.newloan.applicationservice.CreateLoanAccount; import org.mifos.clientportfolio.newloan.applicationservice.GroupMemberAccountDto; import org.mifos.clientportfolio.newloan.applicationservice.LoanAccountCashFlow; import org.mifos.clientportfolio.newloan.applicationservice.LoanApplicationStateDto; import org.mifos.core.MifosRuntimeException; import org.mifos.dto.domain.CashFlowDto; import org.mifos.dto.domain.CreateAccountFeeDto; import org.mifos.dto.domain.CreateAccountPenaltyDto; import org.mifos.dto.domain.CustomerSearchDto; import org.mifos.dto.domain.CustomerSearchResultDto; import org.mifos.dto.domain.FeeDto; import org.mifos.dto.domain.LoanAccountDetailsDto; import org.mifos.dto.domain.LoanCreationInstallmentDto; import org.mifos.dto.domain.LoanPaymentDto; import org.mifos.dto.domain.MandatoryHiddenFieldsDto; import org.mifos.dto.domain.MonthlyCashFlowDto; import org.mifos.dto.domain.PenaltyDto; import org.mifos.dto.screen.CashFlowDataDto; import org.mifos.dto.screen.CustomerSearchResultsDto; import org.mifos.dto.screen.LoanCreationLoanDetailsDto; import org.mifos.dto.screen.LoanCreationProductDetailsDto; import org.mifos.dto.screen.LoanCreationResultDto; import org.mifos.dto.screen.LoanInstallmentsDto; import org.mifos.dto.screen.LoanScheduleDto; import org.mifos.dto.screen.SearchDetailsDto; import org.mifos.dto.screen.UploadedFileDto; import org.mifos.platform.questionnaire.service.InformationOrderServiceFacade; import org.mifos.platform.questionnaire.service.QuestionGroupDetail; import org.mifos.platform.validations.ErrorEntry; import org.mifos.service.BusinessRuleException; import org.mifos.ui.core.controller.util.helpers.LoanCreationHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.binding.message.MessageBuilder; import org.springframework.binding.message.MessageContext; import org.springframework.stereotype.Controller; import org.springframework.web.multipart.commons.CommonsMultipartFile; @SuppressWarnings("PMD") @Controller public class LoanAccountController { private final LoanAccountServiceFacade loanAccountServiceFacade; private final AdminServiceFacade adminServiceFacade; private LoanCreationLoanDetailsDto dto; private LoanControllerHelper loanControllerHelper; @Autowired private InformationOrderServiceFacade informationOrderServiceFacade; @Autowired public LoanAccountController(LoanAccountServiceFacade loanAccountServiceFacade, AdminServiceFacade adminServiceFacade, LoanControllerHelper loanControllerHelper) { this.loanAccountServiceFacade = loanAccountServiceFacade; this.adminServiceFacade = adminServiceFacade; this.loanControllerHelper = loanControllerHelper; } public void markAsRedoLoanAccount(CustomerSearchFormBean formBean) { formBean.setRedoLoanAccount(true); } public void markAsRedoLoanAccount(LoanAccountFormBean formBean) { formBean.setRedoLoanAccount(true); } public CustomerSearchResultsDto searchCustomers(CustomerSearchFormBean formBean, boolean isNewGLIMCreation) { // Search result cap. This is needed until ajax search is implemented. Integer searchCap = 1000; CustomerSearchDto customerSearchDto = new CustomerSearchDto(formBean.getSearchString(), Integer.valueOf(1), searchCap); List<CustomerSearchResultDto> pagedDetails = this.loanAccountServiceFacade.retrieveCustomersThatQualifyForLoans(customerSearchDto, isNewGLIMCreation); //int firstResult = formBean.getPage() * formBean.getPageSize() - (formBean.getPageSize()-1); // FIXME selected pageNumber and pageSize info should be passed in on bean. SearchDetailsDto searchDetails = new SearchDetailsDto(pagedDetails.size(), 1, 1, searchCap); return new CustomerSearchResultsDto(searchDetails, pagedDetails); } public CustomerSearchResultsDto searchPossibleGuarantors (CustomerSearchFormBean formBean, boolean isNewGLIMCreation, Integer clientId, Integer loanId) { //As above, same issues occur (@searchCustomers) Integer searchCap = 1000; CustomerSearchDto customerSearchDto = new CustomerSearchDto(formBean.getSearchString(), Integer.valueOf(1), searchCap); List<CustomerSearchResultDto> pagedDetails = this.loanAccountServiceFacade.retrievePossibleGuarantors(customerSearchDto, isNewGLIMCreation, clientId, loanId); SearchDetailsDto searchDetails = new SearchDetailsDto(pagedDetails.size(), 1, 1, searchCap); return new CustomerSearchResultsDto(searchDetails, pagedDetails); } public void linkGuarantor (Integer guarantorId, Integer loanId){ try{ this.loanAccountServiceFacade.linkGuarantor(guarantorId, loanId); } catch (Exception e){ throw new MifosRuntimeException(); } } public void unlinkGuaranty(Integer guarantorId, Integer loanId) { try { loanAccountServiceFacade.unlinkGuaranty(guarantorId, loanId); } catch (Exception e) { throw new MifosRuntimeException(); } } public LoanCreationProductDetailsDto retrieveLoanProducts(int customerId, org.springframework.binding.message.MessageContext messageContext) { LoanCreationProductDetailsDto loanProductDetails = this.loanAccountServiceFacade.retrieveGetProductDetailsForLoanAccountCreation(customerId); if (loanProductDetails.getErrors().hasErrors()) { List<ErrorEntry> errorList = loanProductDetails.getErrors().getErrorEntries(); for(int i=0; i<errorList.size(); i++){ MessageBuilder builder = new MessageBuilder().error().source(errorList.get(i).getFieldName()) .codes(Arrays.asList(errorList.get(i).getErrorCode()).toArray(new String[1])) .defaultText(errorList.get(i).getDefaultMessage()); messageContext.addMessage(builder.build()); } } return loanProductDetails; } @SuppressWarnings("PMD") public LoanCreationLoanDetailsDto retrieveLoanCreationDetails(int customerId, int productId, String eventId, String fileToDelete, LoanAccountFormBean formBean) { if ("newFileSelected".equals(eventId)) { if (formBean.getSelectedFile() != null) { CommonsMultipartFile file = formBean.getSelectedFile(); formBean.getFiles().add(file); formBean.getFilesMetadata().add( new UploadedFileDto(file.getOriginalFilename(), file.getContentType(), (int) file.getSize(), formBean .getSelectedFileDescription())); } return dto; } else if ("fileDeleted".equals(eventId)) { if (fileToDelete != null) { int index = 0; for(CommonsMultipartFile formFile : formBean.getFiles()) { if (formFile.getOriginalFilename().equals(fileToDelete)) { index = formBean.getFiles().indexOf(formFile); break; } } if (index >= 0) { formBean.getFiles().remove(index); formBean.getFilesMetadata().remove(index); } } return dto; } MandatoryHiddenFieldsDto mandatoryHidden = this.adminServiceFacade.retrieveHiddenMandatoryFieldsToRead(); dto = this.loanAccountServiceFacade.retrieveLoanDetailsForLoanAccountCreation(customerId, Integer.valueOf(productId).shortValue(), formBean.isRedoLoanAccount()); formBean.setLocale(Locale.getDefault()); formBean.setDigitsBeforeDecimalForInterest(dto.getAppConfig().getDigitsBeforeDecimalForInterest()); formBean.setDigitsAfterDecimalForInterest(dto.getAppConfig().getDigitsAfterDecimalForInterest()); formBean.setDigitsBeforeDecimalForMonetaryAmounts(dto.getAppConfig().getDigitsBeforeDecimalForMonetaryAmounts()); formBean.setDigitsAfterDecimalForMonetaryAmounts(dto.getAppConfig().getDigitsAfterDecimalForMonetaryAmounts()); formBean.setProductId(productId); formBean.setCustomerId(dto.getCustomerDetailDto().getCustomerId()); formBean.setRepaymentScheduleIndependentOfCustomerMeeting(dto.isRepaymentIndependentOfMeetingEnabled()); formBean.setGraceDuration(dto.getGracePeriodInInstallments()); formBean.setMaxGraceDuration(dto.getGracePeriodInInstallments()); if (dto.isRepaymentIndependentOfMeetingEnabled()) { // use loan product to default meeting details Integer recursEvery = dto.getLoanOfferingMeetingDetail().getMeetingDetailsDto().getEvery(); Integer dayOfMonth = dto.getLoanOfferingMeetingDetail().getMeetingDetailsDto().getRecurrenceDetails().getDayNumber(); Integer weekOfMonth = dto.getLoanOfferingMeetingDetail().getMeetingDetailsDto().getRecurrenceDetails().getWeekOfMonth(); Integer dayOfWeek = dto.getLoanOfferingMeetingDetail().getMeetingDetailsDto().getRecurrenceDetails().getDayOfWeek(); Integer recurrenceType = dto.getLoanOfferingMeetingDetail().getMeetingDetailsDto().getRecurrenceTypeId(); Integer customerRecurrenceType = dto.getCustomerMeetingDetail().getMeetingDetailsDto().getRecurrenceTypeId(); if (recurrenceType.equals(customerRecurrenceType)) { // if customer and product meeting frequencies are the same e.g. weekly or monthly, then default to customer details except for recurrence details dayOfMonth = dto.getCustomerMeetingDetail().getMeetingDetailsDto().getRecurrenceDetails().getDayNumber(); weekOfMonth = dto.getCustomerMeetingDetail().getMeetingDetailsDto().getRecurrenceDetails().getWeekOfMonth(); dayOfWeek = dto.getCustomerMeetingDetail().getMeetingDetailsDto().getRecurrenceDetails().getDayOfWeek(); } // sometimes it seems customer meeting information can be setup wrong (i.e. has a day of month even though its weekly) if (recurrenceType == 1) { if (dateInformationIsAvailable(dayOfWeek)) { formBean.setWeeklyDetails(dayOfWeek, recursEvery); } } else if (recurrenceType == 2) { if (dateInformationIsAvailable(weekOfMonth) && dateInformationIsAvailable(dayOfWeek)) { formBean.setWeekOfMonthDetails(weekOfMonth, dayOfWeek, recursEvery); } else if (dateInformationIsAvailable(dayOfMonth)) { formBean.setDayOfMonthDetails(dayOfMonth, recursEvery); } } else if (recurrenceType == 3) { formBean.setRepaymentRecursEvery(recursEvery); } } formBean.setVariableInstallmentsAllowed(dto.isVariableInstallmentsAllowed()); if (dto.isVariableInstallmentsAllowed()) { formBean.setMinGapInDays(dto.getMinGapInDays()); formBean.setMaxGapInDays(dto.getMaxGapInDays()); formBean.setMinInstallmentAmount(dto.getMinInstallmentAmount()); } formBean.setGlimApplicable(dto.isGlimApplicable()); if (dto.isGroup()){ formBean.setGroupLoanWithMembersEnabled(dto.isGroupLoanWithMembersEnabled()); } if (dto.isGlimApplicable() || (dto.isGroup() && dto.isGroupLoanWithMembersEnabled())) { List<LoanAccountDetailsDto> clientData = dto.getClientDetails(); String[] clientGlobalIdArray = new String[clientData.size()]; int index = 0; for (LoanAccountDetailsDto loanAccountDetailsDto : clientData) { clientGlobalIdArray[index] = loanAccountDetailsDto.getClientId(); index++; } formBean.setClientGlobalId(clientGlobalIdArray); formBean.setClientSelectForGroup(new Boolean[clientData.size()]); formBean.setClientAmount(new Number[clientData.size()]); Integer[] loanPurpose = new Integer[clientData.size()]; formBean.setClientLoanPurposeId(loanPurpose); Number[][] selectedFeeIndividualAmounts = new Number[3][clientData.size()]; formBean.setSelectedFeeIndividualAmounts(selectedFeeIndividualAmounts); Number[][] defaultFeeIndividualAmounts = new Number[dto.getDefaultFees().size()][clientData.size()]; formBean.setDefaultFeeIndividualAmounts(defaultFeeIndividualAmounts); } else { formBean.setAmount(Double.valueOf(dto.getDefaultLoanAmount().toPlainString())); } formBean.setMinAllowedAmount(dto.getMinLoanAmount()); formBean.setMaxAllowedAmount(dto.getMaxLoanAmount()); formBean.setInterestRate(dto.getDefaultInterestRate()); formBean.setMinAllowedInterestRate(dto.getMinInterestRate()); formBean.setMaxAllowedInterestRate(dto.getMaxInterestRate()); formBean.setNumberOfInstallments(dto.getDefaultNumberOfInstallments()); formBean.setMinNumberOfInstallments(dto.getMinNumberOfInstallments()); formBean.setMaxNumberOfInstallments(dto.getMaxNumberOfInstallments()); formBean.setSourceOfFundsMandatory(mandatoryHidden.isMandatoryLoanSourceOfFund()); formBean.setPurposeOfLoanMandatory(mandatoryHidden.isMandatoryLoanAccountPurpose()); formBean.setCollateralTypeAndNotesHidden(mandatoryHidden.isHideSystemCollateralTypeNotes()); formBean.setExternalIdHidden(mandatoryHidden.isHideSystemExternalId()); if (!mandatoryHidden.isHideSystemExternalId()) { formBean.setExternalIdMandatory(mandatoryHidden.isMandatorySystemExternalId()); } LocalDate possibleDisbursementDate = dto.getNextPossibleDisbursementDate(); if (possibleDisbursementDate != null) { formBean.setDisbursementDateDD(possibleDisbursementDate.getDayOfMonth()); formBean.setDisbursementDateMM(possibleDisbursementDate.getMonthOfYear()); formBean.setDisbursementDateYY(possibleDisbursementDate.getYearOfEra()); } formBean.setCollateralNotes(""); Number[] defaultFeeId = new Number[dto.getDefaultFees().size()]; Number[] defaultFeeAmountOrRate = new Number[dto.getDefaultFees().size()]; int index=0; for (FeeDto defaultFee : dto.getDefaultFees()) { if (defaultFee.isRateBasedFee()) { defaultFeeAmountOrRate[index] = defaultFee.getRate(); } else { defaultFeeAmountOrRate[index] = defaultFee.getAmountAsNumber(); } defaultFeeId[index] = Long.valueOf(defaultFee.getId()); index++; } formBean.setDefaultFeeAmountOrRate(defaultFeeAmountOrRate); formBean.setDefaultFeeId(defaultFeeId); formBean.setDefaultFeeSelected(new Boolean[dto.getDefaultFees().size()]); formBean.setDefaultFees(dto.getDefaultFees()); Number[] defaultPenaltyId = new Number[dto.getDefaultPenalties().size()]; Number[] defaultPenaltyAmountOrRate = new Number[dto.getDefaultPenalties().size()]; int idx=0; for (PenaltyDto defaultPenalty : dto.getDefaultPenalties()) { if (defaultPenalty.isRateBasedPenalty()) { defaultPenaltyAmountOrRate[idx] = defaultPenalty.getRate(); } else { defaultPenaltyAmountOrRate[idx] = defaultPenalty.getAmountAsNumber(); } defaultPenaltyId[idx] = Long.valueOf(defaultPenalty.getPenaltyId()); idx++; } formBean.setDefaultPenaltyAmountOrRate(defaultPenaltyAmountOrRate); formBean.setDefaultPenaltyId(defaultPenaltyId); formBean.setDefaultPenaltySelected(new Boolean[dto.getDefaultPenalties().size()]); formBean.setDefaultPenalties(dto.getDefaultPenalties()); Number[] selectedFeeId = new Number[3]; formBean.setSelectedFeeId(selectedFeeId); Number[] selectedFeeAmount = new Number[3]; formBean.setSelectedFeeAmount(selectedFeeAmount); formBean.setAdditionalFees(dto.getAdditionalFees()); if (formBean.getFiles() == null) { formBean.setFiles(new ArrayList<CommonsMultipartFile>()); formBean.setFilesMetadata(new ArrayList<UploadedFileDto>()); } formBean.setLoanInformationOrder(informationOrderServiceFacade.getInformationOrder("CreateLoan")); return dto; } private boolean dateInformationIsAvailable(Integer dayOfWeek) { return dayOfWeek != null && dayOfWeek > 0; } public void loadQuestionGroups(Integer productId, LoanAccountQuestionGroupFormBean loanAccountQuestionGroupFormBean) { List<QuestionGroupDetail> questionGroups = loanAccountServiceFacade.retrieveApplicableQuestionGroups(productId); loanAccountQuestionGroupFormBean.setQuestionGroups(questionGroups); } public boolean isCompareForCashFlowEnabled(Integer productId) { return this.loanAccountServiceFacade.isCompareWithCashFlowEnabledOnProduct(productId); } public LoanScheduleDto retrieveLoanSchedule(int customerId, int productId, LoanAccountFormBean formBean, BackdatedPaymentable loanScheduleFormBean, boolean resetRedoLoanAccountDetails) { LocalDate disbursementDate = LoanCreationHelper.translateDisbursementDateToLocalDate(formBean); RecurringSchedule recurringSchedule = LoanCreationHelper.determineRecurringSchedule(formBean); List<CreateAccountFeeDto> accountFees = LoanCreationHelper.translateToAccountFeeDtos(formBean); List<CreateAccountFeeDto> additionalAccountFees = LoanCreationHelper.translateToAdditionalAccountFeeDtos(formBean); accountFees.addAll(additionalAccountFees); CreateLoanSchedule createLoanAccount = new CreateLoanSchedule(customerId, productId, BigDecimal.valueOf(formBean.getAmount().doubleValue()), formBean.getInterestRate().doubleValue(), disbursementDate, formBean.getNumberOfInstallments().intValue(), formBean.getGraceDuration().intValue(), formBean.isRepaymentScheduleIndependentOfCustomerMeeting(), recurringSchedule, accountFees); LoanScheduleDto loanSchedule = null; if (formBean.isVariableInstallmentsAllowed() && !loanScheduleFormBean.getInstallments().isEmpty()) { loanSchedule = loanAccountServiceFacade.createLoanSchedule(createLoanAccount, loanScheduleFormBean.getInstallments(), loanScheduleFormBean.getInstallmentAmounts()); } else { loanSchedule = loanAccountServiceFacade.createLoanSchedule(createLoanAccount); } loanControllerHelper.populateFormBeanFromDto(customerId, productId, formBean, loanScheduleFormBean, disbursementDate, loanSchedule, resetRedoLoanAccountDetails); return loanSchedule; } public CashFlowDto retrieveCashFlowSettings(LoanScheduleDto loanScheduleDto, int productId) { DateTime firstInstallment = loanScheduleDto.firstInstallment(); DateTime lastInstallment = loanScheduleDto.lastInstallment(); return loanAccountServiceFacade.retrieveCashFlowSettings(firstInstallment, lastInstallment, productId, BigDecimal.valueOf(loanScheduleDto.getLoanAmount())); } public List<CashFlowDataDto> recalculateCashflowSummaryDetails(CashFlowSummaryFormBean formBean, CashFlowDto cashFlowDto, List<MonthlyCashFlowDto> monthlyCashFlow, LoanScheduleDto loanScheduleDto, int productId) { List<CashFlowDataDto> cashFlowDataDtos = this.loanAccountServiceFacade.retrieveCashFlowSummary(monthlyCashFlow, loanScheduleDto); formBean.setCashFlowDataDtos(cashFlowDataDtos); formBean.setProductId(productId); BigDecimal cashFlowTotalBalance = BigDecimal.ZERO; for (MonthlyCashFlowDto monthlyCashFlowDto : monthlyCashFlow) { cashFlowTotalBalance = cashFlowTotalBalance.add(monthlyCashFlowDto.calculateRevenueMinusExpenses()); } formBean.setMonthlyCashFlows(monthlyCashFlow); formBean.setCashFlowTotalBalance(cashFlowTotalBalance); formBean.setRepaymentCapacity(cashFlowDto.getRepaymentCapacity()); return cashFlowDataDtos; } public List<CashFlowDataDto> retrieveCashflowSummaryDetails(CashFlowSummaryFormBean formBean, CashFlowDto cashFlowDto, List<MonthlyCashFlowDto> monthlyCashFlow, LoanScheduleDto loanScheduleDto, int productId, LoanAccountFormBean loanAccountFormBean) { List<CashFlowDataDto> cashFlowDataDtos = this.loanAccountServiceFacade.retrieveCashFlowSummary(monthlyCashFlow, loanScheduleDto); formBean.setCashFlowDataDtos(cashFlowDataDtos); formBean.setProductId(productId); BigDecimal loanAmount = BigDecimal.valueOf(loanScheduleDto.getLoanAmount()); BigDecimal totalInstallmentAmount = BigDecimal.ZERO; DateTime firstInstallmentDueDate = new DateTime(); DateTime lastInstallmentDueDate = new DateTime(); List<DateTime> installments = new ArrayList<DateTime>(); List<Number> installmentAmounts = new ArrayList<Number>(); if (!loanScheduleDto.getInstallments().isEmpty()) { firstInstallmentDueDate = loanScheduleDto.firstInstallment(); lastInstallmentDueDate = loanScheduleDto.lastInstallment(); for (LoanCreationInstallmentDto installment : loanScheduleDto.getInstallments()) { totalInstallmentAmount = totalInstallmentAmount.add(BigDecimal.valueOf(installment.getTotal())); installments.add(new DateTime(installment.getDueDate())); installmentAmounts.add(installment.getTotal()); } } formBean.setInstallments(installments); formBean.setInstallmentAmounts(installmentAmounts); formBean.setLoanPrincipal(loanAmount); LoanInstallmentsDto loanInstallmentsDto = new LoanInstallmentsDto(loanAmount, totalInstallmentAmount, firstInstallmentDueDate.toDate(), lastInstallmentDueDate.toDate()); BigDecimal cashFlowTotalBalance = BigDecimal.ZERO; for (MonthlyCashFlowDto monthlyCashFlowDto : monthlyCashFlow) { cashFlowTotalBalance = cashFlowTotalBalance.add(monthlyCashFlowDto.calculateRevenueMinusExpenses()); } formBean.setMonthlyCashFlows(monthlyCashFlow); formBean.setLoanInstallmentsDto(loanInstallmentsDto); formBean.setCashFlowTotalBalance(cashFlowTotalBalance); formBean.setRepaymentCapacity(cashFlowDto.getRepaymentCapacity()); LocalDate disbursementDate = LoanCreationHelper.translateDisbursementDateToLocalDate(loanAccountFormBean); loanControllerHelper.populateFormBeanFromDto(loanAccountFormBean.getCustomerId(), productId, loanAccountFormBean, formBean, disbursementDate, loanScheduleDto, true); return cashFlowDataDtos; } public LoanCreationResultDto saveLoanApplicationForLater(LoanAccountFormBean formBean, LoanAccountQuestionGroupFormBean loanAccountQuestionGroupFormBean, LoanAccountCashFlow loanAccountCashFlow, CashFlowSummaryFormBean cashFlowSummaryFormBean, LoanScheduleFormBean loanScheduleFormBean) { LoanApplicationStateDto applicationState = loanAccountServiceFacade.retrieveLoanApplicationState(); return submitLoanApplication(applicationState.getPartialApplicationId(), formBean, loanAccountQuestionGroupFormBean, loanAccountCashFlow, cashFlowSummaryFormBean, loanScheduleFormBean); } public LoanCreationResultDto submitLoanApplication(LoanAccountFormBean formBean, LoanAccountQuestionGroupFormBean loanAccountQuestionGroupFormBean, LoanAccountCashFlow loanAccountCashFlow, CashFlowSummaryFormBean cashFlowSummaryFormBean, LoanScheduleFormBean loanScheduleFormBean, MessageContext messageContext) { LoanApplicationStateDto applicationState = loanAccountServiceFacade.retrieveLoanApplicationState(); try { return submitLoanApplication(applicationState.getConfiguredApplicationId(), formBean, loanAccountQuestionGroupFormBean, loanAccountCashFlow, cashFlowSummaryFormBean, loanScheduleFormBean); } catch (BusinessRuleException e) { MessageBuilder builder = new MessageBuilder() .error() .codes(Arrays.asList(e.getMessageKey()).toArray( new String[1])).defaultText(e.getMessage()) .args(e.getMessageValues()); messageContext.addMessage(builder.build()); throw e; } } public LoanCreationResultDto openLoanWithBackdatedPayments(LoanAccountFormBean formBean, LoanAccountQuestionGroupFormBean loanAccountQuestionGroupFormBean, LoanAccountCashFlow loanAccountCashFlow, CashFlowSummaryFormBean cashFlowSummaryFormBean, LoanScheduleFormBean loanScheduleFormBean, MessageContext messageContext) { LoanApplicationStateDto applicationState = loanAccountServiceFacade.retrieveLoanApplicationState(); try { return submitLoanWithBackdatedPaymentsApplication(applicationState.getPartialApplicationId(), formBean, loanAccountQuestionGroupFormBean, loanAccountCashFlow, cashFlowSummaryFormBean, loanScheduleFormBean); } catch (BusinessRuleException e) { MessageBuilder builder = new MessageBuilder() .error() .codes(Arrays.asList(e.getMessageKey()).toArray( new String[1])).defaultText(e.getMessage()) .args(e.getMessageValues()); messageContext.addMessage(builder.build()); throw e; } } private LoanCreationResultDto submitLoanWithBackdatedPaymentsApplication(Integer accountState, LoanAccountFormBean formBean, LoanAccountQuestionGroupFormBean loanAccountQuestionGroupFormBean, LoanAccountCashFlow loanAccountCashFlow, CashFlowSummaryFormBean cashFlowSummaryFormBean, LoanScheduleFormBean loanScheduleFormBean) { LocalDate disbursementDate = LoanCreationHelper.translateDisbursementDateToLocalDate(formBean); RecurringSchedule recurringSchedule = LoanCreationHelper.determineRecurringSchedule(formBean); List<CreateAccountFeeDto> accountFees = LoanCreationHelper.translateToAccountFeeDtos(formBean); List<CreateAccountPenaltyDto> accountPenalties = LoanCreationHelper.translateToAccountPenaltyDtos(formBean); List<CreateAccountFeeDto> additionalAccountFees = LoanCreationHelper.translateToAdditionalAccountFeeDtos(formBean); accountFees.addAll(additionalAccountFees); BigDecimal loanAmount = BigDecimal.valueOf(formBean.getAmount().doubleValue()); BigDecimal minAllowedLoanAmount = BigDecimal.valueOf(formBean.getMinAllowedAmount().doubleValue()); BigDecimal maxAllowedLoanAmount = BigDecimal.valueOf(formBean.getMaxAllowedAmount().doubleValue()); CreateLoanAccount loanAccountDetails = new CreateLoanAccount(formBean.getCustomerId(), formBean.getProductId(), accountState, loanAmount, minAllowedLoanAmount, maxAllowedLoanAmount, formBean.getInterestRate().doubleValue(), disbursementDate, formBean.getDisbursalPaymentTypeId(), formBean.getNumberOfInstallments().intValue(), formBean.getMinNumberOfInstallments().intValue(), formBean.getMaxNumberOfInstallments().intValue(), formBean.getGraceDuration().intValue(), formBean.getFundId(), formBean.getLoanPurposeId(), formBean.getCollateralTypeId(), formBean.getCollateralNotes(), formBean.getExternalId(), formBean.isRepaymentScheduleIndependentOfCustomerMeeting(), recurringSchedule, accountFees, accountPenalties); List<LoanPaymentDto> backdatedLoanPayments = new ArrayList<LoanPaymentDto>(); int index = 0; List<Number> actualPaymentAmountDetails = cashFlowSummaryFormBean.getActualPaymentAmounts(); if (actualPaymentAmountDetails.isEmpty()) { actualPaymentAmountDetails = loanScheduleFormBean.getActualPaymentAmounts(); } for (Number actualPaymentAmount : actualPaymentAmountDetails) { if (actualPaymentAmount.doubleValue() > 0) { LocalDate transactionDate = new LocalDate(loanScheduleFormBean.getActualPaymentDates().get(index)); backdatedLoanPayments.add(new LoanPaymentDto(actualPaymentAmount.toString(), transactionDate, loanScheduleFormBean.getActualPaymentTypes().get(index), null)); } index++; } LoanCreationResultDto loanCreationResultDto = null; if (formBean.isGlimApplicable()) { List<GroupMemberAccountDto> memberAccounts = createGroupMemberAccounts(formBean); BigDecimal totalLoanAmount = BigDecimal.valueOf(formBean.getAmount().doubleValue()); CreateGlimLoanAccount createGroupLoanAccount = new CreateGlimLoanAccount(memberAccounts, totalLoanAmount, loanAccountDetails); loanCreationResultDto = loanAccountServiceFacade.createBackdatedGroupLoanWithIndividualMonitoring(createGroupLoanAccount, backdatedLoanPayments, loanAccountQuestionGroupFormBean.getQuestionGroups(), loanAccountCashFlow); } else if (formBean.isVariableInstallmentsAllowed()) { List<DateTime> installmentDates = cashFlowSummaryFormBean.getInstallments(); List<Number> installmentPrincipalAmounts = cashFlowSummaryFormBean.getInstallmentAmounts(); if (installmentDates.isEmpty()) { installmentDates = loanScheduleFormBean.getInstallments(); installmentPrincipalAmounts = loanScheduleFormBean.getInstallmentAmounts(); } // api for creating loan with premade loan schedule loanCreationResultDto = loanAccountServiceFacade.createBackdatedLoan(loanAccountDetails, backdatedLoanPayments, loanAccountQuestionGroupFormBean.getQuestionGroups(), loanAccountCashFlow, installmentDates, installmentPrincipalAmounts); } else { loanCreationResultDto = loanAccountServiceFacade.createBackdatedLoan(loanAccountDetails, backdatedLoanPayments, loanAccountQuestionGroupFormBean.getQuestionGroups(), loanAccountCashFlow); } return loanCreationResultDto; } private LoanCreationResultDto submitLoanApplication(Integer accountState, LoanAccountFormBean formBean, LoanAccountQuestionGroupFormBean loanAccountQuestionGroupFormBean, LoanAccountCashFlow loanAccountCashFlow, CashFlowSummaryFormBean cashFlowSummaryFormBean, LoanScheduleFormBean loanScheduleFormBean) { LocalDate disbursementDate = LoanCreationHelper.translateDisbursementDateToLocalDate(formBean); RecurringSchedule recurringSchedule = LoanCreationHelper.determineRecurringSchedule(formBean); List<CreateAccountFeeDto> accountFees = LoanCreationHelper.translateToAccountFeeDtos(formBean); List<CreateAccountFeeDto> additionalAccountFees = LoanCreationHelper.translateToAdditionalAccountFeeDtos(formBean); List<CreateAccountPenaltyDto> accountPenalties = LoanCreationHelper.translateToAccountPenaltyDtos(formBean); accountFees.addAll(additionalAccountFees); BigDecimal loanAmount = BigDecimal.valueOf(formBean.getAmount().doubleValue()); BigDecimal minAllowedLoanAmount = BigDecimal.valueOf(formBean.getMinAllowedAmount().doubleValue()); BigDecimal maxAllowedLoanAmount = BigDecimal.valueOf(formBean.getMaxAllowedAmount().doubleValue()); CreateLoanAccount loanAccountDetails = new CreateLoanAccount(formBean.getCustomerId(), formBean.getProductId(), accountState, loanAmount, minAllowedLoanAmount, maxAllowedLoanAmount, formBean.getInterestRate().doubleValue(), disbursementDate, null, formBean.getNumberOfInstallments().intValue(), formBean.getMinNumberOfInstallments().intValue(), formBean.getMaxNumberOfInstallments().intValue(), formBean.getGraceDuration().intValue(), formBean.getFundId(), formBean.getLoanPurposeId(), formBean.getCollateralTypeId(), formBean.getCollateralNotes(), formBean.getExternalId(), formBean.isRepaymentScheduleIndependentOfCustomerMeeting(), recurringSchedule, accountFees, accountPenalties); LoanCreationResultDto loanCreationResultDto = null; if (formBean.isGlimApplicable()) { List<GroupMemberAccountDto> memberAccounts = createGroupMemberAccounts(formBean); BigDecimal totalLoanAmount = BigDecimal.valueOf(formBean.getAmount().doubleValue()); CreateGlimLoanAccount createGroupLoanAccount = new CreateGlimLoanAccount(memberAccounts, totalLoanAmount, loanAccountDetails); loanCreationResultDto = loanAccountServiceFacade.createGroupLoanWithIndividualMonitoring(createGroupLoanAccount, loanAccountQuestionGroupFormBean.getQuestionGroups(), loanAccountCashFlow); } else { if (formBean.isVariableInstallmentsAllowed()) { List<DateTime> installmentDates = cashFlowSummaryFormBean.getInstallments(); List<Number> totalInstallmentAmounts = cashFlowSummaryFormBean.getInstallmentAmounts(); if (installmentDates.isEmpty()) { installmentDates = loanScheduleFormBean.getInstallments(); totalInstallmentAmounts = loanScheduleFormBean.getInstallmentAmounts(); } // api for creating loan with premade loan schedule loanCreationResultDto = loanAccountServiceFacade.createLoan(loanAccountDetails, loanAccountQuestionGroupFormBean.getQuestionGroups(), loanAccountCashFlow, installmentDates, totalInstallmentAmounts); } else { loanCreationResultDto = loanAccountServiceFacade.createLoan(loanAccountDetails, loanAccountQuestionGroupFormBean.getQuestionGroups(), loanAccountCashFlow); } } List<CommonsMultipartFile> formFiles = formBean.getFiles(); List<UploadedFileDto> filesMetadata = formBean.getFilesMetadata(); for(int i=0; i<formFiles.size(); i++) { if (formFiles.get(i).getSize() != 0) { InputStream inputStream; try { inputStream = formFiles.get(i).getInputStream(); } catch (IOException e) { throw new MifosRuntimeException(); } UploadedFileDto fileMetadata = filesMetadata.get(i); loanAccountServiceFacade.uploadFile(loanCreationResultDto.getAccountId(), inputStream, fileMetadata); } } return loanCreationResultDto; } @SuppressWarnings("PMD") private List<GroupMemberAccountDto> createGroupMemberAccounts(LoanAccountFormBean formBean) { List<GroupMemberAccountDto> memberAccounts = new ArrayList<GroupMemberAccountDto>(); int index = 0; for (Boolean clientSelected : formBean.getClientSelectForGroup()) { if (clientSelected != null && clientSelected.booleanValue()) { String globalId = formBean.getClientGlobalId()[index]; BigDecimal loanAmount = BigDecimal.valueOf(formBean.getClientAmount()[index].doubleValue()); Integer loanPurposeId = formBean.getClientLoanPurposeId()[index]; GroupMemberAccountDto memberAccount = new GroupMemberAccountDto(globalId, loanAmount, loanPurposeId); memberAccounts.add(memberAccount); } index++; } return memberAccounts; } }