/// <summary> /// Sets the Loan request status based on the number of days this /// loan is delayed. /// </summary> /// <param name="loanRequest">LoanRequest to update</param> /// <param name="loan">Loan to be used for the update</param> /// <param name="stmntDate">Date to use to calculate the statement</param> /// <param name="vats">List of applicable VATS</param> /// <param name="intValues">List of applicable Interest Rate valus</param> /// <param name="nrmlzdDate">Normalized date used to set the next status update date.</param> /// <param name="firstPass">Is this the first time this function is called for the loans of a loan request?</param> public void SetLoanRequestStatus(LoanRequest loanRequest, Loan loan, DateTime stmntDate, IList<VAT> vats, IList<InterestRateValue> intValues, DateTime nrmlzdDate, bool firstPass) { try { DateTime nextUpdtDate = nrmlzdDate; /* Calculate the statement to today's day */ LoanStatement stmnt = new LoanStatement (loan, stmntDate, vats, intValues, false); /* Calculate the statement and determine how many days * behind is the loan. */ stmnt.GenerateStatement (); int delayedDays = stmnt.DelayedDays; /* Update the loan statement values stored in the DB */ loan.DelinquentVAT = stmnt.DelinquentVAT; loan.MoratoryInterests = stmnt.MoratoryInterests; loan.DelinquentInterests = stmnt.DelinquentInterests; loan.DelinquentPrincipal = stmnt.DelinquentPrincipal; loan.DelinquentBalance = stmnt.DelinquentBalance; loan.CurrentPrincipal = stmnt.CurrentPrincipal; loan.CurrentInterests = stmnt.CurrentInterests; loan.CurrentVAT = stmnt.CurrentVAT; loan.CurrentCommissions = stmnt.CurrentCommissions; loan.PaymentBalance = stmnt.PaymentBalance; loan.CurrentBalance = stmnt.CurrentBalance; loan.DelayedDays = delayedDays; /* Set the Loan Request Status accordingly. * * Corriente - No Delays * Vencida - Delayed 1 to 3 days (including day 3) * ExtraJudicial - Delayed 4 to 89 days * JudicialAltoRiesgo - Delayed 90 or more * */ if (delayedDays == 0) /* Corriente */ { /* If this is the first loan, set the loan request status */ if (firstPass) { /* Get the next payment date from the day * we calculated this update */ nextUpdtDate = nrmlzdDate; nextUpdtDate = stmnt.GetNextPayment (nrmlzdDate); /* Check one day after the next payment */ nextUpdtDate = nextUpdtDate.AddDays (1); loanRequest.LoanRequestStatus = LoanRequestStatus.Corriente; loanRequest.ContinueStatusUpdates = true; loanRequest.NextStatusUpdate = nextUpdtDate; } else { /* Corriente status takes presedence as long as this is not the first * pass and the following condition is TRUE */ if (loanRequest.LoanRequestStatus != LoanRequestStatus.Vencida && loanRequest.LoanRequestStatus != LoanRequestStatus.ExtraJudicial && loanRequest.LoanRequestStatus != LoanRequestStatus.JudicialAltoRiesgo) { /* Get the next payment date from the day * we calculated this update */ nextUpdtDate = nrmlzdDate; nextUpdtDate = stmnt.GetNextPayment (nrmlzdDate); /* Check one day after the next payment */ nextUpdtDate = nextUpdtDate.AddDays (1); loanRequest.LoanRequestStatus = LoanRequestStatus.Corriente; loanRequest.ContinueStatusUpdates = true; loanRequest.NextStatusUpdate = nextUpdtDate; } else { /* DO NOTHING */ } } } else if (delayedDays >= 1 && delayedDays <= Globals.VENCIDA) { if (firstPass) { nextUpdtDate = nrmlzdDate; nextUpdtDate = GetNextUpdateDate (nextUpdtDate); loanRequest.LoanRequestStatus = LoanRequestStatus.Vencida; loanRequest.ContinueStatusUpdates = true; loanRequest.NextStatusUpdate = nextUpdtDate; } else { /* Vencida status takes presedence as long as this is not the first * pass and the following condition is TRUE */ if (loanRequest.LoanRequestStatus != LoanRequestStatus.ExtraJudicial && loanRequest.LoanRequestStatus != LoanRequestStatus.JudicialAltoRiesgo) { nextUpdtDate = nrmlzdDate; nextUpdtDate = GetNextUpdateDate (nextUpdtDate); loanRequest.LoanRequestStatus = LoanRequestStatus.Vencida; loanRequest.ContinueStatusUpdates = true; loanRequest.NextStatusUpdate = nextUpdtDate; } else { /* DO NOTHING */ } } } else if (delayedDays > Globals.VENCIDA && delayedDays <= Globals.EXTRA_JUDICIAL) { if (firstPass) { nextUpdtDate = nrmlzdDate; nextUpdtDate = GetNextUpdateDate (nextUpdtDate); loanRequest.LoanRequestStatus = LoanRequestStatus.ExtraJudicial; loanRequest.ContinueStatusUpdates = true; loanRequest.NextStatusUpdate = nextUpdtDate; } else { /* ExtraJudicial status takes presedence as long as this is not the first * pass and the following condition is TRUE */ if (loanRequest.LoanRequestStatus != LoanRequestStatus.JudicialAltoRiesgo) { nextUpdtDate = nrmlzdDate; nextUpdtDate = GetNextUpdateDate (nextUpdtDate); loanRequest.LoanRequestStatus = LoanRequestStatus.ExtraJudicial; loanRequest.ContinueStatusUpdates = true; loanRequest.NextStatusUpdate = nextUpdtDate; } else { /* DO NOTHING */ } } } else if (delayedDays >= Globals.JUDICIAL_ALTO_RIESGO) { nextUpdtDate = nrmlzdDate; nextUpdtDate = GetNextUpdateDate (nextUpdtDate); /* JudicialAltoRiesgo takes presedence over every other state */ loanRequest.LoanRequestStatus = LoanRequestStatus.JudicialAltoRiesgo; /* We will stop updating if the delayed days is greater than 180 days */ if (delayedDays > Globals.MAX_UPDATE_DAYS) { loanRequest.ContinueStatusUpdates = false; } else { loanRequest.ContinueStatusUpdates = true; } loanRequest.NextStatusUpdate = nextUpdtDate; } } /* If the exception was thrown here, just pass it up */ catch (ZiblerBusinessComponentsException ex) { throw; } /* Catch any Data Layer or other exception and throw an unkown exception */ catch (Exception ex) { ZiblerBusinessComponentsUnknownException exc = new ZiblerBusinessComponentsUnknownException (ex); /* Throw the new exception */ throw exc; } }
/// <summary> /// Generates a report with estimated payment amounts on a Target Date. Only /// Loans that have payments on the Target Date are contemplated. Balances are /// calculated using todays date. /// </summary> /// <param name="financialInstitution">Financial Institution</param> /// <param name="targetDate">Target Date to be used for calculation</param> /// <param name="startIndex">startIndex</param> /// <param name="maxResults">maxResults</param> /// <param name="totalRecords">totalRecords</param> /// <returns>LoanRecoveryEstimatedRecoveryReport</returns> public IList<LoanRecoveryEstimatedRecoveryReport> GetLoanRecoveryEstimatedRecoveryReport( string financialInstitution, DateTime targetDate, int startIndex, int maxResults, out int totalRecords) { try { ILoanRequestDAO loanRequestDAO = _daoFactory.GetLoanRequestDAO (); ILoanDAO loanDAO = _daoFactory.GetLoanDAO (); IInterestRateDAO interestRateDAO = _daoFactory.GetInterestRateDAO (); IInterestRateValueDAO interestRateValueDAO = _daoFactory.GetInterestRateValueDAO (); IVatDAO vatDAO = _daoFactory.GetVatDAO (); IList<LoanRecoveryEstimatedRecoveryReport> reports = loanRequestDAO.GetLoanRecoveryEstimatedRecoveryReport (financialInstitution, targetDate, startIndex, maxResults, out totalRecords); /* Make sure we got at least one */ if (reports.Count <= 0) { throw new ZiblerBusinessComponentsException ( Resources.ReportOperationsLoanRequestNotExist); } /* Hash table to store Loan Ids along with their respective InterestRate Ids */ Hashtable hashLoanIds = new Hashtable (); /* Hash table to store unique Interest Rate Ids and the earliest date from * where their values are needed. This is to avoid getting the same * Interest Rates more than onces if they are repeated. */ Hashtable hashIntRtDates = new Hashtable (); /* List of Interest Rate values for a given Interest Rate Id */ Hashtable hashIntRtValues = new Hashtable (); /* Earliest date from where the VAT values are needed */ DateTime? vatStart = null; /* Loop through the returned report objects and get the * Loan Ids, Interest Rates and VAT dates */ foreach (LoanRecoveryEstimatedRecoveryReport rep in reports) { /* Add the loan Id and its Interest Rate Id to the list of * hashLoanIds */ if (!hashLoanIds.Contains (rep.LoanId)) hashLoanIds.Add (rep.LoanId, rep.InterestRateId); /* Add the Interest Rate Id and the Loan authorization date * to the hashIntRtDates list. This list is used to minimize the number * of queries made to the database if the Interest Rate Id is the * same for multiple loans */ if (!hashIntRtDates.Contains (rep.InterestRateId)) { hashIntRtDates.Add (rep.InterestRateId, rep.AuthorizationDate); } /*Add the start date only if it is previous to the current one */ if (hashIntRtDates[rep.InterestRateId] == null) hashIntRtDates[rep.InterestRateId] = rep.AuthorizationDate; else { /* Get the date associated to the Interest Rate */ DateTime currDate = Convert.ToDateTime (hashIntRtDates[rep.InterestRateId]); /* Determine if there is another loan (rep.AuthorizationDate) whose * date is earlier than the previously assigned to the Interest Rate Id. * If so (replace) then use this date as the new data so later we get * all the interest rate values from there */ bool replace = DateUtilities.IsFirstDateGreaterThanSecondDate (currDate, rep.AuthorizationDate); if (replace) hashIntRtDates[rep.InterestRateId] = rep.AuthorizationDate; } /* If we don't have a VAT date yet, use the current AuthorizationDate */ if (vatStart == null) vatStart = Convert.ToDateTime (rep.AuthorizationDate); else { /* Determine if the loan has an earlier date than the currently selected for * the VAT. If so, then this date should be used to search for the VAT */ bool replace = DateUtilities.IsFirstDateGreaterThanSecondDate ( vatStart.Value, rep.AuthorizationDate); if (replace) vatStart = Convert.ToDateTime (rep.AuthorizationDate); } } /* Verify we have at least one loan Id */ if (hashLoanIds.Count <= 0) throw new ZiblerBusinessComponentsException ( Resources.ReportOperationsLoanRequestWithOutLoans); /* Get all the loan Ids from our hash table. */ IDictionaryEnumerator enLoanIds = hashLoanIds.GetEnumerator (); IList<int> processLoanIds = new List<int> (); while (enLoanIds.MoveNext ()) { /* Add the loan Id to a list of loan Ids which will be used * to retrieved them from the Database */ processLoanIds.Add (Convert.ToInt32 (enLoanIds.Key)); } /* Retrieve the Loans from the Database */ IList<Loan> loans = loanDAO.GetLoan (processLoanIds); /* Get all the Interests and their values to be used to calculate * the statements for all the loans */ IDictionaryEnumerator en = hashIntRtDates.GetEnumerator (); while (en.MoveNext ()) { /* Interest Rate needed */ int intRateId = Convert.ToInt32 (en.Key); /* Values needed from this date */ DateTime dt = Convert.ToDateTime (en.Value); IList<InterestRateValue> list = interestRateValueDAO.GetInterestRateValuesForStatement ( intRateId, dt, DateTime.Today); /* If no interest rate value was returned, it means that a value does not exists * for a given Interest Rate Id */ if (list == null) { /* Get the interest rate for informational purposes */ InterestRate intRate = interestRateDAO.FindById (intRateId); if (intRate != null) { string intRateName = intRate.Name; throw new ZiblerBusinessComponentsException ( String.Format ( Resources.ReportOperationsInterestRateDateNotAvailable, intRateName, dt.ToShortDateString ())); } } /* Add the values to a hash list and move on */ hashIntRtValues.Add (intRateId, list); } /* Get all the VATs */ IList<VAT> vats = vatDAO.GetVATsForStatement (financialInstitution, vatStart.Value, DateTime.Today); if (vats.Count <= 0) throw new ZiblerBusinessComponentsException ( Resources.ReportOperationsNoVatsAvailable); /* Now that we have all the required data, loop through the list of reports one more time * and calculate the Statement for each one of them */ foreach (LoanRecoveryEstimatedRecoveryReport report in reports) { /* Calculated the statement on each loan of the report */ foreach (Loan loan in loans) { if (report.LoanId == loan.Id) { int loanId = loan.Id; int intValueId = Convert.ToInt32 (hashLoanIds[loanId]); IList<InterestRateValue> intValues = (IList<InterestRateValue>)hashIntRtValues[intValueId]; /* Calculate the statement to today's day */ LoanStatement stmnt = new LoanStatement (loan, DateTime.Today, vats, intValues); stmnt.GenerateStatement (); report.DelayedDays = stmnt.DelayedDays; report.DelinquentInterests = stmnt.DelinquentInterests; report.DelinquentPrincipal = stmnt.DelinquentPrincipal; report.DelinquentVAT = stmnt.DelinquentVAT; report.DelinquentBalance = stmnt.DelinquentBalance; report.LoanedAmount = stmnt.LoanedAmount; report.LoanType = stmnt.LoanType; report.MoratoryInterests = stmnt.MoratoryInterests; /* Get the payment number on the target date, so we can * determine what the estimated payment will be */ report.EstmtdNxtPymnt = stmnt.GetEstimatedPayment (report.PaymentNumber); break; } } } return reports; } /* If the exception was thrown here, just pass it up */ catch (ZiblerBusinessComponentsException ex) { throw; } /* Catch any Data Layer or other exception and throw an unkown exception */ catch (Exception ex) { ZiblerBusinessComponentsUnknownException exc = new ZiblerBusinessComponentsUnknownException (ex); /* Throw the new exception */ throw exc; } }
/// <summary> /// Gets a loan recovery main report /// </summary> /// <param name="financialInstitution"></param> /// <param name="startDate">Start Authorization DAte</param> /// <param name="endDate">End Authorization date</param> /// <param name="startIndex"></param> /// <param name="maxResults"></param> /// <param name="totalRecords"></param> /// <returns></returns> public IList<LoanRecoveryMainReport> GetLoanRecoveryMainReport(string financialInstitution, DateTime startDate, DateTime endDate, int startIndex, int maxResults, out int totalRecords) { try { ILoanRequestDAO loanRequestDAO = _daoFactory.GetLoanRequestDAO (); ILoanDAO loanDAO = _daoFactory.GetLoanDAO (); IInterestRateDAO interestRateDAO = _daoFactory.GetInterestRateDAO (); IInterestRateValueDAO interestRateValueDAO = _daoFactory.GetInterestRateValueDAO (); IVatDAO vatDAO = _daoFactory.GetVatDAO (); IList<LoanRecoveryMainReport> reports = loanRequestDAO.GetLoanRecoveryMainReport ( financialInstitution, startDate, endDate, startIndex, maxResults, out totalRecords); if (reports.Count <= 0) { throw new ZiblerBusinessComponentsException ( Resources.ReportOperationsLoanRequestNotExist); } Hashtable loanIds = new Hashtable (); Hashtable hashTable = new Hashtable (); Hashtable hashIntRtValues = new Hashtable (); DateTime? vatStart = null; /* Now that we have the Loan Recovery Main Report we need to calculate the statements * for the loans involved */ foreach (LoanRecoveryMainReport rep in reports) { /* Add the loan Id and its Interest Rate Id to the list of * loanIds */ if (!loanIds.Contains (rep.LoanId)) loanIds.Add (rep.LoanId, rep.InterestRateId); /* Add the Interest Rate Id and the Loan authorization date * to the local list. This list is used to minimize the number * of queries made to the database if the Interest Rate Id is the * same for multiple loans */ if (!hashTable.Contains (rep.InterestRateId)) { hashTable.Add (rep.InterestRateId, rep.AuthorizationDate); } /*Add the start date only if it is previous to the current one */ if (hashTable[rep.InterestRateId] == null) hashTable[rep.InterestRateId] = rep.AuthorizationDate; else { /* Get the date associated to the Interest Rate */ DateTime currDate = Convert.ToDateTime (hashTable[rep.InterestRateId]); /* Determine if there is another loan (rep.AuthorizationDate) whose * date is earlier than the previously assigned to the Interest Rate Id. * If so (replace) then use this date as the new data so later we get * all the interest rate values from there */ bool replace = DateUtilities.IsFirstDateGreaterThanSecondDate (currDate, rep.AuthorizationDate); if (replace) hashTable[rep.InterestRateId] = rep.AuthorizationDate; } if (vatStart == null) vatStart = Convert.ToDateTime (rep.AuthorizationDate); else { /* Determine if the loan has an earlier date than the currently selected for * the VAT. If so, then this date should be used to search for the VAT */ bool replace = DateUtilities.IsFirstDateGreaterThanSecondDate ( vatStart.Value, rep.AuthorizationDate); if (replace) vatStart = Convert.ToDateTime (rep.AuthorizationDate); } } if (loanIds.Count <= 0) { throw new ZiblerBusinessComponentsException ( Resources.ReportOperationsLoanRequestWithOutLoans); } /* Get all the loan Ids */ IDictionaryEnumerator enLoanIds = loanIds.GetEnumerator (); IList<int> temp = new List<int> (); while (enLoanIds.MoveNext ()) { temp.Add (Convert.ToInt32 (enLoanIds.Key)); } IList<Loan> loans = loanDAO.GetLoan (temp); /* Get all the Interests and their values to be used to calculate * the statements for all the loans */ IDictionaryEnumerator en = hashTable.GetEnumerator (); while (en.MoveNext ()) { /* Interest Rate needed */ int intRateId = Convert.ToInt32 (en.Key); /* Values needed from this date */ DateTime dt = Convert.ToDateTime (en.Value); IList<InterestRateValue> list = interestRateValueDAO.GetInterestRateValuesForStatement ( intRateId, dt, DateTime.Today); /* If no interest rate value was returned, it means that a value does not exists * for a given Interest Rate Id */ if (list == null) { /* Get the interest rate for informational purposes */ InterestRate intRate = interestRateDAO.FindById (intRateId); if (intRate != null) { string intRateName = intRate.Name; throw new ZiblerBusinessComponentsException ( String.Format ( Resources.ReportOperationsInterestRateDateNotAvailable, intRateName, dt.ToShortDateString ())); } } hashIntRtValues.Add (intRateId, list); } /* Get all the VATs */ IList<VAT> vats = vatDAO.GetVATsForStatement (financialInstitution, vatStart.Value, DateTime.Today); if (vats.Count <= 0) throw new ZiblerBusinessComponentsException ( Resources.ReportOperationsNoVatsAvailable); foreach (LoanRecoveryMainReport report in reports) { /* Now that we have all the values, calculate the statements and update the report * object */ foreach (Loan loan in loans) { if (report.LoanId == loan.Id) { int loanId = loan.Id; int intValueId = Convert.ToInt32 (loanIds[loanId]); IList<InterestRateValue> intValues = (IList<InterestRateValue>)hashIntRtValues[intValueId]; LoanStatement stmnt = new LoanStatement (loan, DateTime.Today, vats, intValues); stmnt.GenerateStatement (); report.CommissionsTotal = stmnt.CommissionsTotal; report.CurrentCommissions = stmnt.CurrentCommissions; report.CurrentInterests = stmnt.CurrentInterests; report.CurrentPrincipal = stmnt.CurrentPrincipal; report.CurrentVAT = stmnt.CurrentVAT; report.CurrentBalance = stmnt.CurrentBalance; report.DelayedDays = stmnt.DelayedDays; report.DelinquentInterests = stmnt.DelinquentInterests; report.DelinquentPrincipal = stmnt.DelinquentPrincipal; report.DelinquentVAT = stmnt.DelinquentVAT; report.DelinquentBalance = stmnt.DelinquentBalance; report.LoanedAmount = stmnt.LoanedAmount; report.LoanType = stmnt.LoanType; report.MoratoryInterests = stmnt.MoratoryInterests; report.TotalAmountPaid = stmnt.TotalAmountPaid; report.PaymentBalance = stmnt.PaymentBalance; break; } } } return reports; } /* If the exception was thrown here, just pass it up */ catch (ZiblerBusinessComponentsException ex) { throw; } /* Catch any Data Layer or other exception and throw an unkown exception */ catch (Exception ex) { ZiblerBusinessComponentsUnknownException exc = new ZiblerBusinessComponentsUnknownException (ex); /* Throw the new exception */ throw exc; } }
/// <summary> /// Gets the loan statement. /// </summary> /// <param name="financialInstitution">The financial institution.</param> /// <param name="loan">The loan.</param> /// <param name="statementDate">The statement date.</param> /// <returns>Loan Statement</returns> public LoanStatement GetLoanStatement(string financialInstitution, Loan loan, DateTime statementDate) { try { IFinancialInstitutionDAO financialInstitutionDAO = _daoFactory.GetFinancialInstitutionDAO (); IInterestRateValueDAO interestRateValueDAO = _daoFactory.GetInterestRateValueDAO (); IVatDAO vatDAO = _daoFactory.GetVatDAO (); if (loan == null) throw new ZiblerBusinessComponentsException (Resources.RecordNotFound); FinancialInstitution finInst = financialInstitutionDAO.GetFinancialInstitutionByName (financialInstitution); if (finInst == null) throw new ZiblerBusinessComponentsUnknownException (); /* Check the statement date is not before the start */ if (!DateUtilities.IsFirstDateGreaterOrEqualThanSecondDate ( Convert.ToDateTime (statementDate), Convert.ToDateTime (loan.StartDate))) { throw new ZiblerBusinessComponentsException ( Resources.LoanOperationsMsgStatementDateIsBeforeLoan); } if (loan.EndDate == null) throw new ZiblerBusinessComponentsUnknownException (); /* Get all the VATS within the range */ IList<VAT> vats = vatDAO.GetVATsForStatement (financialInstitution, Convert.ToDateTime (loan.StartDate), statementDate); /* Make sure there is at least one from the beginning of the loan */ bool vatFound = false; if (vats != null) { foreach (VAT vat in vats) { if (!DateUtilities.IsFirstDateGreaterThanSecondDate ( Convert.ToDateTime (vat.ValidFrom), Convert.ToDateTime (loan.StartDate))) { vatFound = true; break; } } } if (!vatFound) { throw new ZiblerBusinessComponentsException ( Resources.LoanOperationsMsgNoVATsInSystem); } /* Get the interest Rate Values */ IList<InterestRateValue> interestValues = interestRateValueDAO.GetInterestRateValuesForStatement (loan.InterestRate.Id, Convert.ToDateTime ( loan.StartDate), statementDate); /* Make sure there is at least one from the beginning of the loan */ bool intFound = false; if (interestValues != null) { foreach (InterestRateValue val in interestValues) { if (!DateUtilities.IsFirstDateGreaterThanSecondDate ( Convert.ToDateTime (val.ValidFrom), Convert.ToDateTime (loan.StartDate))) { intFound = true; break; } } } if (!intFound) { throw new ZiblerBusinessComponentsException ( Resources.LoanOperationsMsgNoInterestRateValu); } /* Generate the statement */ LoanStatement loanStatement = new LoanStatement (loan, statementDate, vats, interestValues); loanStatement.GenerateStatement (); return loanStatement; } /* If the exception was thrown here, just pass it up */ catch (ZiblerBusinessComponentsException ex) { throw; } /* Catch any Data Layer or other exception and throw an unkown exception */ catch (Exception ex) { ZiblerBusinessComponentsUnknownException exc = new ZiblerBusinessComponentsUnknownException (ex); /* Throw the new exception */ throw exc; } }