package com.fitbank.installment; import java.math.BigDecimal; import java.sql.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import com.fitbank.common.ApplicationDates; import com.fitbank.common.Helper; import com.fitbank.common.QuotaBean; import com.fitbank.common.RequestData; import com.fitbank.common.exception.FitbankException; import com.fitbank.common.helper.CalculationBase; import com.fitbank.common.helper.Constant; import com.fitbank.common.helper.Dates; import com.fitbank.fin.helper.FinancialParameters; import com.fitbank.hb.persistence.gene.Tsystemparametercompany; import com.fitbank.hb.persistence.gene.TsystemparametercompanyKey; /** * Clase que se encarga de generar tabla de pagos manual. * * @author Soft WareHouse S.A. * */ public class ManualInstallment extends AbstractQuota { private BigDecimal capitalinquotas = Constant.BD_ZERO; /** Interese acumulado de cuotas deudoras. */ private BigDecimal debtorinterest = Constant.BD_ZERO; /** * Valor de cuota fija ajustada. */ private BigDecimal fixquota = Constant.BD_ZERO; /** * Indica si se realizo o no el ajuste de una cuota fija. */ private boolean adjustquota = true; private boolean manualQuota = false; @Override public void calculate(InstallmentTable pQuotaTable) throws Exception { quotaTable = pQuotaTable; reducedcapital = quotaTable.getAmount(); quotanumber = pQuotaTable.getBegincalculationperiod(); fixquota = quotaTable.getFixquota(); if (!quotaTable.isFixedQuota()) { // calcula el numero de cuotas, cuando se conoce el plazo de la // operacion. super.calculateTotalperiod(pQuotaTable); } // Calulate grace quotas. this.generateGrace(); boolean end = false; if (!quotaTable.isFixedQuota()) { this.obtainFixquota(end); // Ajuste de valor de cuota fija si es una sola cuota no se ajusta if (adjustquota && pQuotaTable.isAdjustquota() && (quotanumber - quotaTable.getBegincalculationperiod()) != 0) { this.adjustQuote(); } } else { while (!end) { super.globalIntrest = Constant.BD_ZERO; super.calculatePayDate(quotaTable); if (quotaTable.getAmount().subtract(capitalinquotas) .compareTo(fixquota) < 0) { end = true; } // calcula intereses, comiones,seguros para la cuota. super.processByCategory(debtorinterest, false); this.calculateCuota(end); quotanumber++; } /* Se resta 1 al numero de cuotas */ quotaTable.setTotalperiod(--quotanumber); } } /** * Calcula tabla de pago dado una cuota fija. * * @throws Exception */ protected void calculateCuota(boolean pEnd) throws Exception { BigDecimal capital = Constant.BD_ZERO; // Si el valor total de intereses y comisiones excede del valor de la // cuota fija if (super.globalIntrest.compareTo(this.fixquota) > 0) { // Se acumula el valor de intereses y comisiones excedente de la // cuota y se asume como el // valor de intereses y comisiones de la cuota el valor de la cuota this.debtorinterest = this.debtorinterest.add(this.globalIntrest .subtract(this.fixquota)); this.globalIntrest = this.fixquota; // Si se tiene un valor acumulado de intereses y comisiones // proveniente de cuotas anteriores } else if (this.debtorinterest.compareTo(Constant.BD_ZERO) > 0) { BigDecimal aux = this.fixquota.subtract(this.globalIntrest); BigDecimal value; if (this.debtorinterest.compareTo(aux) > 0) { value = aux; } else { value = this.debtorinterest; } this.debtorinterest = this.debtorinterest.subtract(value); this.globalIntrest = this.globalIntrest.add(value); } // Distribuye el interes deudor si exitiera. this.distributeDebtorInterest(pEnd); // Si se trata de la ultima cuota if (pEnd) { // Define el valor de Intereses mas Comisiones de la cuota por si // hay un residuo en la ultima cuota // Carga todo el capital reducido al capital de la cuota capital = this.reducedcapital; // this.reducedcapital = this.reducedcapital.subtract(this.capital); } else { // Obtiene el valor de capital de la cuota capital = this.fixquota.subtract(this.globalIntrest); } // validar limite de dia inicial if (super.globalIntrest.compareTo(capital) > 0) { validateInitialDay(getParameter()); } super.addQuota(this.quotanumber, this.reducedcapital, capital, true); if (!pEnd) { reducedcapital = reducedcapital.subtract(capital); } capitalinquotas = capitalinquotas.add(capital); } /** * Distribuye el interes, comision, seguros hasta completar el valor de la * cuota. * * @param pEnd * Indica si es la ultinma cuota de la tabla de pagos. * @throws Exception */ private void distributeDebtorInterest(boolean pEnd) throws Exception { BigDecimal intrestToDistribute = this.globalIntrest; BigDecimal totalIntrest; Iterator> itr = this.mCategoryRates.values() .iterator(); while (itr.hasNext()) { for (CategoryRate categoryRate : itr.next()) { totalIntrest = categoryRate.getIntrest().add( categoryRate.getDebtorinterest()); // Si el valor total de interes o comision de la categoria // excede el valor total definido de interes a distribuir y no // se trata de la ultima cuota if (totalIntrest.compareTo(intrestToDistribute) > 0 && !pEnd) { // Se acumula el valor de interes excedente de la categoria // y se asume como el valor de interes de la categoria el // valor total definido de interes a distribuir categoryRate.setDebtorinterest(totalIntrest .subtract(intrestToDistribute)); categoryRate.setIntrest(intrestToDistribute); } else { categoryRate.setIntrest(totalIntrest); categoryRate.setDebtorinterest(totalIntrest .subtract(categoryRate.getIntrest())); } // Se obtiene el nuevo valor de interes a distribuir intrestToDistribute = intrestToDistribute.subtract(categoryRate .getIntrest()); } }// end while } /** * Genera cuotas de interes por el numero de periodos de gracia definidos * para la tabla. * * @throws Exception */ private void generateGrace() throws Exception { if (quotaTable.getGraceperiod() > 0) { for (int i = 0; i < quotaTable.getGraceperiod(); i++) { super.calculatePayDate(quotaTable); // this.calculateIntrestCommission(quotaTable,reducedcapital); super.processByCategory(false); super.addQuota(quotanumber, reducedcapital, Constant.BD_ZERO, true); quotanumber++; } } } /** * Si el valor de la ultima cuota es diferente del valor de la cuota fija, * se obtiene un nuevo valor de cuota fija con aproimaciones sucesivas. * * @throws Exception */ private void adjustQuote() throws Exception { if (this.getLastquote().compareTo(quotaTable.getFixquota()) != 0) { BigDecimal quotavalue = null; if (FinancialParameters.getInstance() .getBooleanValue("nominalrate")) { AdjustFixedInstallment adjustFixedQuota = new AdjustFixedInstallment(); quotavalue = adjustFixedQuota.calculate(quotaTable); // quotavalue = // quotavalue.add(quotaTable.getOtherChargesQuota()); } else { AdjustFixedInstallmentCapitalize adjustFixedQuota = new AdjustFixedInstallmentCapitalize(); quotavalue = adjustFixedQuota.calculate(quotaTable); // quotavalue = // quotavalue.add(quotaTable.getOtherChargesQuota()); } quotaTable.setFixquota(quotavalue); quotaTable.getQuotasBean().clear(); quotaTable.getQuotaCategoryBean().clear(); super.setPreviouspaydate(null); super.setNextpaydate(null); super.totaldays = 0; this.adjustquota = false; quotanumber = quotaTable.getBegincalculationperiod(); this.calculate(quotaTable); } } /** * Entrega el valor de la ultima cuota. * * @return * @throws Exception */ private BigDecimal getLastquote() throws Exception { QuotaBean quotaBean = null; for (QuotaBean quota : quotaTable.getQuotasBean()) { quotaBean = quota; } BigDecimal valuequota = quotaBean.getCapital() .add(quotaBean.getInteres()) .add(quotaBean.getComision().add(quotaBean.getCargo())); valuequota = valuequota.add(quotaBean.getAcciones()); return valuequota; } /** * Cambia los parametros de las cuota, para generar una tabla especial. * * @throws Exception */ private void changeParameters() throws Exception { Map> mdata = quotaTable.getMspecial(); if (mdata == null) { return; } Map mquota = mdata.get(this.quotanumber); if (mquota == null) { return; } this.manualQuota = true; this.fixquota = (BigDecimal) mquota.get("cuota"); super.nextpaydate = (Date) mquota.get("fvencimiento"); super.totaldays = super.totaldays - super.daysperquota; Dates dates = null; if (quotaTable.isFixday() && !(quotaTable.getPayday() != null && quotaTable.getPayday() .compareTo(31) == 0)) { dates = new Dates(this.nextpaydate, CalculationBase.B360360); } else { dates = new Dates(this.nextpaydate, quotaTable.getCalculationBase()); } Dates inicialday = new Dates(this.previouspaydate, quotaTable.getCalculationBase()); int days = dates.substract(inicialday); this.setDaysperquota(days); } /** * Entrega el valor de la cuota fija, si no tiene una la calcula. * * @throws Exception */ private void calculateFixquota() throws Exception { FixedInstallment fixCuota = new FixedInstallment( quotaTable.getCalculationBase()); Integer quotas = quotaTable.getTotalperiod() - quotanumber + Constant.BD_ONE_INTEGER; this.fixquota = fixCuota .calculate(this.reducedcapital, quotaTable.getFinalrate(), quotaTable.getTotalFixedValue(), quotaTable.getDaysperperiod(), quotas, quotaTable.getCurrency()); } /** * Recupera valor de cuota Fija * * @param end * @return * @throws Exception */ private boolean obtainFixquota(boolean end) throws Exception { int size = quotaTable.getTotalperiod() - quotaTable.getGraceperiod(); size = size + quotaTable.getBegincalculationperiod() - 1; for (int i = quotaTable.getBegincalculationperiod(); i <= size; i++) { // BigDecimal quotavalue = this.fixquota; super.globalIntrest = Constant.BD_ZERO; super.calculatePayDate(quotaTable); if (manualQuota) { manualQuota = false; this.calculateFixquota(); } // cambia condiciones de cuotas especiales. this.changeParameters(); if (i == size) { end = true; } // calcula intereses, comiones,seguros para la cuota. super.processByCategory(debtorinterest, false); this.calculateCuota(end); // this.fixquota = quotavalue; if (super.stop) { break; } quotanumber++; } return end; } /** * Metodo para validar el limite de dias inicial * * @param diasEx */ private void validateInitialDay(boolean daysExceed) { if (daysExceed) { throw new FitbankException("COL047", "DIAS DE PAGO INICIAL EXCEDE EL LIMITE PERMITIDO"); } } /** * Recuperar Parametro del Sistema para controlar el limite de dia de pago * inicial * * @param diasEx * @return */ private boolean getParameter() { TsystemparametercompanyKey key = new TsystemparametercompanyKey( RequestData.getDetail().getCompany(), "DIAPAGOEXCEDE", ApplicationDates.DEFAULT_EXPIRY_TIMESTAMP); Tsystemparametercompany tsystemparametercompany = (Tsystemparametercompany) Helper .getSession().get(Tsystemparametercompany.class, key); return tsystemparametercompany != null && tsystemparametercompany.getValortexto() != null && tsystemparametercompany.getValortexto().compareTo("1") == 0; } }