/*
* 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.application.servicefacade;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.mifos.accounts.fees.business.FeeBO;
import org.mifos.accounts.fees.persistence.FeeDao;
import org.mifos.accounts.financial.business.GLCodeEntity;
import org.mifos.accounts.financial.business.service.GeneralLedgerDao;
import org.mifos.accounts.fund.business.FundBO;
import org.mifos.accounts.fund.persistence.FundDao;
import org.mifos.accounts.penalties.business.PenaltyBO;
import org.mifos.accounts.penalties.persistence.PenaltyDao;
import org.mifos.accounts.productdefinition.LoanAmountCalculation;
import org.mifos.accounts.productdefinition.LoanInstallmentCalculation;
import org.mifos.accounts.productdefinition.LoanProductCaluclationTypeAssembler;
import org.mifos.accounts.productdefinition.business.GracePeriodTypeEntity;
import org.mifos.accounts.productdefinition.business.LoanOfferingBO;
import org.mifos.accounts.productdefinition.business.PrdApplicableMasterEntity;
import org.mifos.accounts.productdefinition.business.PrdStatusEntity;
import org.mifos.accounts.productdefinition.business.ProductCategoryBO;
import org.mifos.accounts.productdefinition.persistence.LoanProductDao;
import org.mifos.accounts.productdefinition.persistence.PrdOfferingPersistence;
import org.mifos.accounts.productdefinition.util.helpers.ApplicableTo;
import org.mifos.accounts.productdefinition.util.helpers.GraceType;
import org.mifos.accounts.productdefinition.util.helpers.InterestType;
import org.mifos.accounts.productdefinition.util.helpers.PrdStatus;
import org.mifos.accounts.productdefinition.util.helpers.ProductDefinitionConstants;
import org.mifos.application.master.business.InterestTypesEntity;
import org.mifos.application.master.business.MifosCurrency;
import org.mifos.application.meeting.util.helpers.RecurrenceType;
import org.mifos.config.AccountingRules;
import org.mifos.core.MifosRuntimeException;
import org.mifos.dto.domain.LoanProductRequest;
import org.mifos.dto.domain.ProductDetailsDto;
import org.mifos.framework.exceptions.PersistenceException;
import org.mifos.framework.util.helpers.Money;
import org.mifos.security.MifosUser;
public class LoanProductAssembler {
private final LoanProductDao loanProductDao;
private final GeneralLedgerDao generalLedgerDao;
private final FundDao fundDao;
private final PenaltyDao penaltyDao;
private LoanProductCaluclationTypeAssembler loanProductCaluclationTypeAssembler = new LoanProductCaluclationTypeAssembler();
public LoanProductAssembler(LoanProductDao loanProductDao, GeneralLedgerDao generalLedgerDao, FundDao fundDao,
PenaltyDao penaltyDao) {
this.loanProductDao = loanProductDao;
this.generalLedgerDao = generalLedgerDao;
this.fundDao = fundDao;
this.penaltyDao = penaltyDao;
}
public LoanOfferingBO fromDto(MifosUser user, LoanProductRequest loanProductRequest) {
try {
Integer userId = user.getUserId();
ProductDetailsDto productDetails = loanProductRequest.getProductDetails();
String name = productDetails.getName();
String shortName = productDetails.getShortName();
String description = productDetails.getDescription();
Integer category = productDetails.getCategory();
boolean loanCycleCounter = loanProductRequest.isIncludeInLoanCycleCounter();
boolean waiverInterest = loanProductRequest.isWaiverInterest();
PrdStatusEntity activeStatus = new PrdOfferingPersistence().getPrdStatus(PrdStatus.LOAN_ACTIVE);
PrdStatusEntity inActiveStatus = new PrdOfferingPersistence().getPrdStatus(PrdStatus.LOAN_INACTIVE);
PrdStatusEntity selectedStatus = activeStatus;
if (productDetails.getStatus() != null
&& inActiveStatus.getOfferingStatusId().equals(productDetails.getStatus().shortValue())) {
selectedStatus = inActiveStatus;
}
MifosCurrency currency = Money.getDefaultCurrency();
if (AccountingRules.isMultiCurrencyEnabled()) {
currency = AccountingRules.getCurrencyByCurrencyId(loanProductRequest.getCurrencyId().shortValue());
}
ProductCategoryBO productCategory = this.loanProductDao.findActiveProductCategoryById(category);
DateTime startDate = productDetails.getStartDate();
DateTime endDate = productDetails.getEndDate();
ApplicableTo applicableTo = ApplicableTo.fromInt(productDetails.getApplicableFor());
PrdApplicableMasterEntity applicableToEntity = this.loanProductDao.findApplicableProductType(applicableTo);
LoanAmountCalculation loanAmountCalculation = this.loanProductCaluclationTypeAssembler
.assembleLoanAmountCalculationFromDto(loanProductRequest.getLoanAmountDetails());
InterestType interestType = InterestType.fromInt(loanProductRequest.getInterestRateType());
Double minRate = loanProductRequest.getInterestRateRange().getMin().doubleValue();
Double maxRate = loanProductRequest.getInterestRateRange().getMax().doubleValue();
Double defaultRate = loanProductRequest.getInterestRateRange().getTheDefault().doubleValue();
InterestTypesEntity interestTypeEntity = this.loanProductDao.findInterestType(interestType);
RecurrenceType recurrence = RecurrenceType.fromInt(loanProductRequest.getRepaymentDetails()
.getFrequencyType().shortValue());
Integer recurEvery = loanProductRequest.getRepaymentDetails().getRecurs();
LoanInstallmentCalculation loanInstallmentCalculation = this.loanProductCaluclationTypeAssembler
.assembleLoanInstallmentCalculationFromDto(loanProductRequest.getRepaymentDetails()
.getInstallmentCalculationDetails());
GraceType gracePeriodType = GraceType
.fromInt(loanProductRequest.getRepaymentDetails().getGracePeriodType());
GracePeriodTypeEntity gracePeriodTypeEntity = this.loanProductDao.findGracePeriodType(gracePeriodType);
Integer gracePeriodDuration = loanProductRequest.getRepaymentDetails().getGracePeriodDuration();
List<FeeBO> applicableFees = new ArrayList<FeeBO>();
List<Integer> applicableFeeIds = loanProductRequest.getApplicableFees();
for (Integer feeId : applicableFeeIds) {
FeeBO fee = ApplicationContextProvider.getBean(FeeDao.class).findById(feeId.shortValue());
applicableFees.add(fee);
}
List<FundBO> applicableFunds = new ArrayList<FundBO>();
List<Integer> applicableFundIds = loanProductRequest.getAccountDetails().getApplicableFunds();
for (Integer fundId : applicableFundIds) {
FundBO fund = this.fundDao.findById(fundId.shortValue());
applicableFunds.add(fund);
}
List<PenaltyBO> applicablePenalties = new ArrayList<PenaltyBO>();
List<Integer> applicablePenaltyIds = loanProductRequest.getApplicablePenalties();
for (Integer penaltyId : applicablePenaltyIds) {
PenaltyBO penalty = this.penaltyDao.findPenaltyById(penaltyId);
applicablePenalties.add(penalty);
}
GLCodeEntity interestGlCode = this.generalLedgerDao.findGlCodeById(loanProductRequest.getAccountDetails()
.getInterestGlCodeId().shortValue());
GLCodeEntity principalGlCode = this.generalLedgerDao.findGlCodeById(loanProductRequest.getAccountDetails()
.getPrincipalClCodeId().shortValue());
String globalProductId = generateProductGlobalNum(user);
LoanOfferingBO loanProduct = LoanOfferingBO.createNew(userId, globalProductId, name, shortName,
description, productCategory, startDate, endDate, applicableToEntity, currency, interestTypeEntity,
minRate, maxRate, defaultRate, recurrence, recurEvery, interestGlCode, principalGlCode,
activeStatus, inActiveStatus, gracePeriodTypeEntity, gracePeriodDuration, waiverInterest,
loanCycleCounter, loanAmountCalculation, loanInstallmentCalculation, applicableFees,
applicableFunds, applicablePenalties);
loanProduct.updateStatus(selectedStatus);
return loanProduct;
} catch (PersistenceException e) {
throw new MifosRuntimeException(e);
}
}
private String generateProductGlobalNum(MifosUser user) {
StringBuilder globalPrdOfferingNum = new StringBuilder();
globalPrdOfferingNum.append(user.getBranchId());
globalPrdOfferingNum.append("-");
try {
Short maxPrdID = new PrdOfferingPersistence().getMaxPrdOffering();
globalPrdOfferingNum.append(StringUtils.leftPad(String.valueOf(maxPrdID != null ? maxPrdID + 1
: ProductDefinitionConstants.DEFAULTMAX + 1), 3, '0'));
return globalPrdOfferingNum.toString();
} catch (PersistenceException e) {
throw new MifosRuntimeException(e);
}
}
}