/** * 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.service; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType; import org.mifosplatform.portfolio.charge.domain.ChargePaymentMode; import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; import org.mifosplatform.portfolio.charge.domain.ChargeTimeType; import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeAddedException; import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants; import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; import org.mifosplatform.portfolio.loanaccount.domain.LoanChargeRepository; import org.mifosplatform.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.mifosplatform.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge; import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct; import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository; import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @Service public class LoanChargeAssembler { private final FromJsonHelper fromApiJsonHelper; private final ChargeRepositoryWrapper chargeRepository; private final LoanChargeRepository loanChargeRepository; private final LoanProductRepository loanProductRepository; @Autowired public LoanChargeAssembler(final FromJsonHelper fromApiJsonHelper, final ChargeRepositoryWrapper chargeRepository, final LoanChargeRepository loanChargeRepository, final LoanProductRepository loanProductRepository) { this.fromApiJsonHelper = fromApiJsonHelper; this.chargeRepository = chargeRepository; this.loanChargeRepository = loanChargeRepository; this.loanProductRepository = loanProductRepository; } public Set<LoanCharge> fromParsedJson(final JsonElement element, Set<LoanDisbursementDetails> disbursementDetails) { JsonArray jsonDisbursement = this.fromApiJsonHelper.extractJsonArrayNamed("disbursementData", element); List<Long> disbursementChargeIds = new ArrayList<>(); if (jsonDisbursement != null && jsonDisbursement.size() > 0) { for (int i = 0; i < jsonDisbursement.size(); i++) { final JsonObject jsonObject = jsonDisbursement.get(i).getAsJsonObject(); if (jsonObject != null && jsonObject.getAsJsonPrimitive(LoanApiConstants.loanChargeIdParameterName) != null) { String chargeIds = jsonObject.getAsJsonPrimitive(LoanApiConstants.loanChargeIdParameterName).getAsString(); if (chargeIds != null) { if (chargeIds.indexOf(",") != -1) { String[] chargeId = chargeIds.split(","); for (String loanChargeId : chargeId) { disbursementChargeIds.add(Long.parseLong(loanChargeId)); } } else { disbursementChargeIds.add(Long.parseLong(chargeIds)); } } } } } final Set<LoanCharge> loanCharges = new HashSet<>(); final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element); final Integer numberOfRepayments = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element); final Long productId = this.fromApiJsonHelper.extractLongNamed("productId", element); final LoanProduct loanProduct = this.loanProductRepository.findOne(productId); if (loanProduct == null) { throw new LoanProductNotFoundException(productId); } final boolean isMultiDisbursal = loanProduct.isMultiDisburseLoan(); LocalDate expectedDisbursementDate = null; if (element.isJsonObject()) { final JsonObject topLevelJsonElement = element.getAsJsonObject(); final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement); final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); if (topLevelJsonElement.has("charges") && topLevelJsonElement.get("charges").isJsonArray()) { final JsonArray array = topLevelJsonElement.get("charges").getAsJsonArray(); for (int i = 0; i < array.size(); i++) { final JsonObject loanChargeElement = array.get(i).getAsJsonObject(); final Long id = this.fromApiJsonHelper.extractLongNamed("id", loanChargeElement); final Long chargeId = this.fromApiJsonHelper.extractLongNamed("chargeId", loanChargeElement); final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalNamed("amount", loanChargeElement, locale); final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerNamed("chargeTimeType", loanChargeElement, locale); final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerNamed("chargeCalculationType", loanChargeElement, locale); final LocalDate dueDate = this.fromApiJsonHelper .extractLocalDateNamed("dueDate", loanChargeElement, dateFormat, locale); final Integer chargePaymentMode = this.fromApiJsonHelper.extractIntegerNamed("chargePaymentMode", loanChargeElement, locale); if (id == null) { final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeId); if (chargeDefinition.isOverdueInstallment()) { final String defaultUserMessage = "Installment charge cannot be added to the loan."; throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null, chargeDefinition.getName()); } ChargeTimeType chargeTime = null; if (chargeTimeType != null) { chargeTime = ChargeTimeType.fromInt(chargeTimeType); } ChargeCalculationType chargeCalculation = null; if (chargeCalculationType != null) { chargeCalculation = ChargeCalculationType.fromInt(chargeCalculationType); } ChargePaymentMode chargePaymentModeEnum = null; if (chargePaymentMode != null) { chargePaymentModeEnum = ChargePaymentMode.fromInt(chargePaymentMode); } if (!isMultiDisbursal) { final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, principal, amount, chargeTime, chargeCalculation, dueDate, chargePaymentModeEnum, numberOfRepayments); loanCharges.add(loanCharge); } else { if (topLevelJsonElement.has("disbursementData") && topLevelJsonElement.get("disbursementData").isJsonArray()) { final JsonArray disbursementArray = topLevelJsonElement.get("disbursementData").getAsJsonArray(); if (disbursementArray.size() > 0) { JsonObject disbursementDataElement = disbursementArray.get(0).getAsJsonObject(); expectedDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed( LoanApiConstants.disbursementDateParameterName, disbursementDataElement, dateFormat, locale); } } if ( ChargeTimeType.DISBURSEMENT.getValue().equals(chargeDefinition.getChargeTimeType())) { for (LoanDisbursementDetails disbursementDetail : disbursementDetails) { LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = null; if (chargeDefinition.isPercentageOfApprovedAmount() && disbursementDetail.expectedDisbursementDateAsLocalDate().equals(expectedDisbursementDate)) { final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, principal, amount, chargeTime, chargeCalculation, dueDate, chargePaymentModeEnum, numberOfRepayments); loanCharges.add(loanCharge); loanTrancheDisbursementCharge = new LoanTrancheDisbursementCharge(loanCharge, disbursementDetail); loanCharge.updateLoanTrancheDisbursementCharge(loanTrancheDisbursementCharge); } else { if (disbursementDetail.expectedDisbursementDateAsLocalDate().equals(expectedDisbursementDate)) { final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), amount, chargeTime, chargeCalculation, disbursementDetail.expectedDisbursementDateAsLocalDate(), chargePaymentModeEnum, numberOfRepayments); loanCharges.add(loanCharge); loanTrancheDisbursementCharge = new LoanTrancheDisbursementCharge(loanCharge, disbursementDetail); loanCharge.updateLoanTrancheDisbursementCharge(loanTrancheDisbursementCharge); } } } } else if (ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().equals(chargeDefinition.getChargeTimeType())) { LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = null; for (LoanDisbursementDetails disbursementDetail : disbursementDetails) { if (ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().equals(chargeDefinition.getChargeTimeType())) { final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), amount, chargeTime, chargeCalculation, disbursementDetail.expectedDisbursementDateAsLocalDate(), chargePaymentModeEnum, numberOfRepayments); loanCharges.add(loanCharge); loanTrancheDisbursementCharge = new LoanTrancheDisbursementCharge(loanCharge, disbursementDetail); loanCharge.updateLoanTrancheDisbursementCharge(loanTrancheDisbursementCharge); } } } else { final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, principal, amount, chargeTime, chargeCalculation, dueDate, chargePaymentModeEnum, numberOfRepayments); loanCharges.add(loanCharge); } } } else { final Long loanChargeId = id; final LoanCharge loanCharge = this.loanChargeRepository.findOne(loanChargeId); if (disbursementChargeIds.contains(loanChargeId) && loanCharge == null) { // throw new // LoanChargeNotFoundException(loanChargeId); } if (loanCharge != null) { loanCharge.update(amount, dueDate, numberOfRepayments); loanCharges.add(loanCharge); } } } } } return loanCharges; } public Set<Charge> getNewLoanTrancheCharges(final JsonElement element) { final Set<Charge> associatedChargesForLoan = new HashSet<>(); if (element.isJsonObject()) { final JsonObject topLevelJsonElement = element.getAsJsonObject(); if (topLevelJsonElement.has("charges") && topLevelJsonElement.get("charges").isJsonArray()) { final JsonArray array = topLevelJsonElement.get("charges").getAsJsonArray(); for (int i = 0; i < array.size(); i++) { final JsonObject loanChargeElement = array.get(i).getAsJsonObject(); final Long id = this.fromApiJsonHelper.extractLongNamed("id", loanChargeElement); final Long chargeId = this.fromApiJsonHelper.extractLongNamed("chargeId", loanChargeElement); if (id == null) { final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeId); if (chargeDefinition.getChargeTimeType() == ChargeTimeType.TRANCHE_DISBURSEMENT.getValue()) { associatedChargesForLoan.add(chargeDefinition); } } } } } return associatedChargesForLoan; } }