public void AddSpreadedFeeTest() { const long loanID = 4; DateTime now = DateTime.UtcNow; List<NL_LoanFees> fees = new List<NL_LoanFees>(); NL_LoanFees f1 = new NL_LoanFees() { LoanFeeTypeID = (int)NLFeeTypes.ServicingFee, Amount = 20, AssignedByUserID = 1, AssignTime = now, CreatedTime = now, Notes = "test servicing", LoanID = loanID }; fees.Add(f1); NL_LoanFees f2 = new NL_LoanFees() { LoanFeeTypeID = (int)NLFeeTypes.ServicingFee, Amount = 20, AssignedByUserID = 1, AssignTime = now.AddMonths(1), CreatedTime = now, Notes = "test servicing", LoanID = loanID }; fees.Add(f2); fees.ForEach(f => m_oLog.Debug(f)); int result = this.m_oDB.ExecuteNonQuery("NL_LoanFeesSave", CommandSpecies.StoredProcedure, this.m_oDB.CreateTableParameter<NL_LoanFees>("Tbl", fees)); m_oLog.Debug(result); }
//[Transactional] public void NL_SyncFees(int id) { Log.DebugFormat("sync NL fees for old loan {0}", id); var loan = this._loans.Get(id); try { long nlLoanId = this.serviceClient.Instance.GetLoanByOldID(id, loan.Customer.Id, this._context.UserId).Value; if (nlLoanId > 0) { NL_Model nlModel = this.serviceClient.Instance.GetLoanState(loan.Customer.Id, nlLoanId, DateTime.UtcNow, this._context.UserId, false).Value; Log.InfoFormat("nlModel : {0} loan: {1} >>>", nlModel, loan); // new/edit fee foreach (LoanCharge ch in loan.Charges.OrderBy(ff => ff.Date)) { NL_LoanFees f = nlModel.Loan.Fees.FirstOrDefault(ff => ff.OldFeeID == ch.Id); if (f == null) { f = new NL_LoanFees() { AssignedByUserID = this._context.UserId, LoanFeeTypeID = (int)NL_Model.ConfVarToNLFeeType(ch.ChargesType), LoanID = nlLoanId, OldFeeID = ch.Id, // update in strategy after this [Transactional] Amount = ch.Amount, AssignTime = ch.Date.Date, Notes = !string.IsNullOrEmpty(ch.Description) ? ch.Description : "add fee from edit loan" }; this.serviceClient.Instance.SaveFee(this._context.UserId, loan.Customer.Id, f); // fee type is editable + modified (amount/assign date/notes) } else if (Array.Exists <NLFeeTypes>(NL_Model.NLFeeTypesEditable, element => element == (NLFeeTypes)f.LoanFeeTypeID) && (f.Amount != ch.Amount || f.AssignTime.Date != ch.Date.Date || f.Notes != ch.Description)) { f.UpdatedByUserID = this._context.UserId; f.Amount = ch.Amount; f.AssignTime = ch.Date.Date; f.Notes = !string.IsNullOrEmpty(ch.Description) ? ch.Description : "add fee from edit loan"; this.serviceClient.Instance.SaveFee(this._context.UserId, loan.Customer.Id, f); } } // removed fee foreach (NL_LoanFees f in nlModel.Loan.Fees.OrderBy(ff => ff.AssignTime)) { var charge = loan.Charges.FirstOrDefault(c => c.Id == f.LoanFeeID); if (charge == null) { f.DeletedByUserID = this._context.UserId; this.serviceClient.Instance.CancelFee(this._context.UserId, loan.Customer.Id, f); } } } // ReSharper disable once CatchAllClause } catch (Exception ex) { Log.InfoFormat("Fail to sync NL loan fees. {0}, err: {1}", Environment.StackTrace, ex.Message); } }
} // SaveFee public StringActionResult CancelFee(int userID, int customerID, NL_LoanFees fee) { CancelFee s = new CancelFee(fee); s.Context.UserID = userID; s.Context.CustomerID = customerID; var amd = ExecuteSync(out s, customerID, userID, fee); return(new StringActionResult { Value = s.Error }); } // CancelFee
public void CancelFeeTest() { NL_LoanFees f = m_oDB.FillFirst<NL_LoanFees>("NL_LoanFeesGet", CommandSpecies.StoredProcedure, new QueryParameter("LoanID", 3), new QueryParameter("LoanFeeID", 20011)); f.DeletedByUserID = 357; CancelFee s = new CancelFee(f); try { s.Execute(); } catch (Exception e) { m_oLog.Debug(e); } }
public void AddLateFeeTest() { const long loanID = 17; DateTime now = new DateTime(2015, 12, 28); NL_LoanFees fee = new NL_LoanFees() { LoanFeeTypeID = (int)NLFeeTypes.AdminFee, Amount = decimal.Parse(CurrentValues.Instance.AdministrationCharge.Value), //NL_Model.GetLateFeesAmount(NLFeeTypes.AdminFee), AssignedByUserID = 1, AssignTime = now, CreatedTime = now, Notes = "test late fee3", LoanID = loanID }; int result = this.m_oDB.ExecuteNonQuery("NL_LoanFeesSave", CommandSpecies.StoredProcedure, this.m_oDB.CreateTableParameter<NL_LoanFees>("Tbl", fee)); m_oLog.Debug(result); }
public void SaveFeeUpdateTest() { NL_LoanFees f = m_oDB.FillFirst<NL_LoanFees>("NL_LoanFeesGet", CommandSpecies.StoredProcedure, new QueryParameter("LoanID", 3), new QueryParameter("LoanFeeID", 20011)); f.UpdatedByUserID = 357; f.UpdateTime = DateTime.UtcNow; f.Amount = 29; f.AssignTime = DateTime.Now.Date.AddDays(-30); SaveFee s = new SaveFee(f); try { s.Execute(); } catch (Exception e) { m_oLog.Debug(e); } }
public void SaveFeeNewTest() { NL_LoanFees f = new NL_LoanFees() { LoanID = 3, Amount = 54, AssignedByUserID = 357, AssignTime = DateTime.UtcNow, CreatedTime = DateTime.UtcNow, LoanFeeTypeID = (int)NLFeeTypes.OtherCharge, Notes = "other fee", UpdatedByUserID = 357 }; SaveFee s = new SaveFee(f); try { s.Execute(); } catch (Exception e) { m_oLog.Debug(e); } }
/// <exception cref="ArgumentNullException"><paramref /> is null. </exception> /// <exception cref="FormatException"><paramref /> is not in the correct format. </exception> public override void Execute() { if (!CurrentValues.Instance.NewLoanRun) { NL_AddLog(LogType.Info, "NL disabled by configuration", null, null, null, null); return; } this.strategyArgs = new object[] { CustomerID, LoanID }; if (CustomerID == 0) { Error = NL_ExceptionCustomerNotFound.DefaultMessage; NL_AddLog(LogType.DataExsistense, "Strategy failed", this.strategyArgs, null, Error, null); return; } if (LoanID == 0) { Error = NL_ExceptionLoanNotFound.DefaultMessage; NL_AddLog(LogType.DataExsistense, "Strategy failed", this.strategyArgs, null, Error, null); return; } // TODO EZ-4330 /* RolloverPayment = open interest till accept day included + rollover fees assigned 1. records NL_Payments (+NL_PaypointTransactions) for rollover () - via AddPayment strategy from outside - via customer dashboard before this strategy 2. record rollover fee for into NL_LoanFees 3. update existing rollover record: [CustomerActionTime], [IsAccepted] in [dbo].[NL_LoanRollovers] table 5. make rollover using calculator - add to NL model new history, rearrange schedules, statuses * - run calc.GetState to get outstanding balance * - create new history * - mark non relevant schedules as CancelledOnRollover * - create schedule for new history 6. update DB: records new history, new schedule items; update previous schedule with appropriate statuses */ DateTime nowTime = DateTime.Now; bool rolloverAccepted = false; NL_AddLog(LogType.Info, "Strategy Start", this.strategyArgs, null, Error, null); // fetch loan's rollovers and check rollover exists, valid and not accepted yet NL_LoanRollovers rollover=DB.Fill<NL_LoanRollovers>("NL_RolloversGet", CommandSpecies.StoredProcedure, new QueryParameter("LoanID", LoanID)) .FirstOrDefault(r => r.DeletedByUserID == null && r.DeletionTime == null && r.IsAccepted == false && (r.CreationTime <= nowTime && nowTime <= r.ExpirationTime)); if (rollover == null) { Error = string.Format("Rollover opportunity for loan {0} not found, or expired, or accepted", LoanID); Log.Info(Error); NL_AddLog(LogType.DataExsistense, "Strategy end", this.strategyArgs, null, Error, null); rolloverAccepted = true; } if (!rolloverAccepted) { // set rollover data for future update rollover.IsAccepted = true; rollover.CustomerActionTime = nowTime; ConnectionWrapper pconn = DB.GetPersistent(); try { // insert rollover fee NL_LoanFees rolloverFee = new NL_LoanFees() { LoanID = LoanID, Amount = Decimal.Parse(CurrentValues.Instance.RolloverCharge.Value), AssignedByUserID = rollover.CreatedByUserID, AssignTime = rollover.CustomerActionTime.Value, CreatedTime = rollover.CustomerActionTime.Value, //DateTime.UtcNow, LoanFeeTypeID = (int)NLFeeTypes.RolloverFee, Notes = string.Format("rolloverID {2} {0:d}-{1:d}", rollover.CreationTime, rollover.ExpirationTime, rollover.LoanRolloverID) }; rollover.LoanFeeID = DB.ExecuteScalar<long>("NL_LoanFeesSave", CommandSpecies.StoredProcedure, DB.CreateTableParameter<NL_LoanFees>("Tbl", rolloverFee)); Log.Info("NL rollover fee {0} added", rollover.LoanFeeID); NL_AddLog(LogType.Info, "Rollover fee added", this.strategyArgs, rollover.LoanFeeID, Error, null); // set newly created history ID for rollover row //rollover.LoanHistoryID = loanState.Result.Loan.LastHistory().LoanHistoryID; // update rollover DB.ExecuteNonQuery("NL_LoanRolloverUpdate", CommandSpecies.StoredProcedure, DB.CreateTableParameter<NL_LoanRollovers>("Tbl", rollover), new QueryParameter("RolloverID", rollover.LoanRolloverID)); pconn.Commit(); //ReSharper disable once CatchAllClause } catch (Exception ex) { pconn.Rollback(); Error = ex.Message; Log.Error("Failed to 'accept rollover': {0}", Error); NL_AddLog(LogType.Error, "Strategy failed", this.strategyArgs, Error, ex.ToString(), ex.StackTrace); return; } } // update "old" schedules, add new history + new schedules + new distributed fees to DB UpdateLoanDBState updateState = new UpdateLoanDBState(CustomerID, LoanID, 1); try { updateState.Execute(); // ReSharper disable once CatchAllClause } catch (Exception ex) { Error = ex.Message; Log.Alert(Error); NL_AddLog(LogType.Error, "Strategy failed", this.strategyArgs, null, Error, null); } // reassign payments and save try { updateState.Execute(); // ReSharper disable once CatchAllClause } catch (Exception ex) { Error = ex.Message; Log.Alert(Error); NL_AddLog(LogType.Error, "Strategy failed", this.strategyArgs, null, Error, null); } }
public CancelFee(NL_LoanFees fee) { Fee = fee; this.strategyArgs = new object[] { Fee }; }
// fee public LoanEvent(DateTime date, NL_LoanFees fee) : this(new DateTime(date.Year, date.Month, date.Day, 23, 59, 57)) { Fee = fee; }
public void IsInTest() { NL_LoanFees f = new NL_LoanFees() { LoanFeeTypeID = 8 }; Console.WriteLine(Array.Exists<NLFeeTypes>(NL_Model.NLFeeTypesEditable, element => element == (NLFeeTypes)f.LoanFeeTypeID)); }
} //Execute private void NLMarkLoanAsLate(NLLateLoansJobModel model) { Log.Debug("NLMarkLoanAsLate: {0}", model.ToString()); NL_AddLog(LogType.Info, "NLMarkLoanAsLate", model, null, null, null); if (model.LoanStatus != NLLoanStatuses.Late) { // DON'T REMOVE!!!!!!!!!! SHOULD BE UNCOMMENT AFTER "old" job cancellation //DB.ExecuteNonQuery( // "UpdateCustomer", CommandSpecies.StoredProcedure, // new QueryParameter("CustomerId", customerId), // new QueryParameter("LoanStatus", "Late"), // new QueryParameter("IsWasLate", true) // ); DB.ExecuteNonQuery("NL_LoanUpdate", CommandSpecies.StoredProcedure, new QueryParameter("LoanID", model.LoanID), new QueryParameter("LoanStatusID", (int)NLLoanStatuses.Late)); Log.Debug("Updating nlloan {0} to late", model.LoanID); NL_AddLog(LogType.Info, "updating loan to late", model, model.LoanID, null, null); } if (model.ScheduleStatus != NLScheduleStatuses.Late) { DB.ExecuteNonQuery("NL_LoanSchedulesUpdate", CommandSpecies.StoredProcedure, new QueryParameter("LoanScheduleID", model.LoanScheduleID), new QueryParameter("LoanScheduleStatusID", (int)NLScheduleStatuses.Late)); Log.Debug("Updating schedule {0} to late", model.LoanScheduleID); NL_AddLog(LogType.Info, "updating schedule to late", model, model.LoanScheduleID, null, null); } GetLoanState loanState = new GetLoanState(model.CustomerID, model.LoanID, now); loanState.Execute(); decimal interest = loanState.Result.Interest; // TODO check: real unpaid interest for this date here if (!LateFeesAllowed(loanState.Result.Loan.LoanOptions, model.LoanID)) { Log.Debug("late fees for loan {0} not allowed", model.LoanID); NL_AddLog(LogType.Info, "Late fees not allowed", model, loanState.Result.Loan.LoanOptions, null, null); return; } int daysLate = (int)(now - model.PlannedDate).TotalDays; int feeAmount; NLFeeTypes feeType; NL_Model.CalculateFee(daysLate, interest, out feeAmount, out feeType); Log.Debug("calculated feeAmount={0}, FeeType={1} daysLate={2} schedule={3} loan={4}", feeAmount, (int)feeType, daysLate, model.LoanScheduleID, model.LoanID); NL_AddLog(LogType.Info, "calculated fee data", model, new object[] { daysLate, interest, feeAmount, feeType }, null, null); if (feeType != NLFeeTypes.None) { // check if this fee type for this schedule already assigned // get next schedule date NL_LoanSchedules nextSchedule = null; loanState.Result.Loan.Histories.ForEach(h => nextSchedule = h.Schedule.FirstOrDefault(s => s.PlannedDate > model.PlannedDate)); DateTime dateTo = nextSchedule == null ? model.PlannedDate : nextSchedule.PlannedDate; // between this and nect schedules same fee alread assigned if (loanState.Result.Loan.Fees.FirstOrDefault(f => f.LoanFeeTypeID == (int)feeType && f.AssignTime.Date <= dateTo.Date && f.AssignTime.Date >= model.PlannedDate) != null) { Log.Debug("NL: Tried to apply already assigned late charge for customer {0} loan {1}: feetype: {2}", model.CustomerID, model.LoanID, feeType); NL_AddLog(LogType.Info, "LatefeeExists", model, feeType, null, null); return; } NL_LoanFees lateFee = new NL_LoanFees() { AssignedByUserID = 1, LoanID = model.LoanID, Amount = feeAmount, AssignTime = now.Date, CreatedTime = now, LoanFeeTypeID = (int)feeType, Notes = daysLate + " days late;schedule " + model.LoanScheduleID, DeletedByUserID = null, DisabledTime = null }; var nlfList = new List <NL_LoanFees>(); nlfList.Add(lateFee); try { DB.ExecuteNonQuery("NL_LoanFeesSave", CommandSpecies.StoredProcedure, DB.CreateTableParameter <NL_LoanFees>("Tbl", nlfList)); Log.Debug("NL: Applied late charge for customer {0} loan {1}: data: {2}", model.CustomerID, model.LoanID, lateFee); NL_AddLog(LogType.Info, "Latefee", model, lateFee, null, null); // ReSharper disable once CatchAllClause } catch (Exception ex) { Log.Alert("NL: Failed to add late fee for customer {0} loan {1}: data: {2}", model.CustomerID, model.LoanID, lateFee); NL_AddLog(LogType.Error, "Failed to add late fee", model, lateFee, ex.ToString(), ex.StackTrace); } } } //NL_MarkLoanAsLate