/Release/1/Dev/BillsPresentation/PaymentReminderPresenter.cs
C# | 361 lines | 232 code | 35 blank | 94 comment | 36 complexity | fb5eb4beb40a345c5156d696135b47cd MD5 | raw file
- using System;
- using BillsDomain;
- using System.ComponentModel;
- using System.Globalization;
-
- namespace BillsPresentation
- {
- /// <summary>
- /// Business logic for the payment reminder view
- /// </summary>
- public class PaymentReminderPresenter
- {
- /// <summary>
- /// Gets or sets the controller.
- /// </summary>
- /// <value>The controller.</value>
- public IScheduledPaymentController Controller { get; set; }
-
- /// <summary>
- /// The view
- /// </summary>
- private IPaymentReminderView view;
-
- /// <summary>
- /// The list of all days and their balances for the graph on the view
- /// </summary>
- private BindingList<CalendarDay> allDaysInARangeForGraph = new BindingList<CalendarDay>();
-
- /// <summary>
- /// The list of days with payments for the monthly calendar on the view
- /// </summary>
- private BindingList<CalendarDay> allDaysInARangeForCalendar = new BindingList<CalendarDay>();
-
- /// <summary>
- /// The list of upcoming payments
- /// </summary>
- private UpcomingPaymentsCollection upcomingPayments = new UpcomingPaymentsCollection();
-
- /// <summary>
- /// Initializes a new instance of the PaymentReminderPresenter class.
- /// </summary>
- /// <param name="view">The view.</param>
- /// <param name="controller">The controller.</param>
- public PaymentReminderPresenter(IPaymentReminderView view, IScheduledPaymentController controller)
- {
- this.view = view;
- this.Controller = controller;
- this.SubscribeViewToEvents();
- }
-
- /// <summary>
- /// Subscribes the view to events.
- /// </summary>
- public void SubscribeViewToEvents()
- {
- this.view.Load += view_Load;
- this.view.AsOfDateChanged += this.OnAsOfDateChanged;
- this.view.AsOfDateChanged += this.OnProjectedBalanceItemsChanged;
- this.view.FormClose += this.OnFormClosing;
- this.view.ScheduledPaymentChanged += this.OnScheduledPaymentChanged;
- this.Controller.ListChanged += this.OnControllerListChanged;
- this.view.DeleteClicked += this.OnDeleteClicked;
- this.view.ProjectedBalanceItemsChanged += this.OnProjectedBalanceItemsChanged;
- this.view.SpecificDateSelected += OnSpecificDateSelected;
- }
-
- /// <summary>
- /// Called when a specific date is selected.
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The <see cref="BillsPresentation.DateSelectedEventArgs"/> instance containing the event data.</param>
- private void OnSpecificDateSelected(object sender, DateSelectedEventArgs e)
- {
- this.PopulateCalendar();
- int i = 0;
- CalendarDay currentCalendarDay = this.allDaysInARangeForCalendar[i];
- while (e.SelectedDate.Date != currentCalendarDay.Date.Date && i < this.allDaysInARangeForCalendar.Count)
- {
- i++;
- currentCalendarDay = this.allDaysInARangeForCalendar[i] as CalendarDay;
- }
-
- this.view.PaymentsForADay = currentCalendarDay.Payments;
- }
-
- /// <summary>
- /// Called when projected balance items changed.
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
- private void OnProjectedBalanceItemsChanged(object sender, EventArgs e)
- {
- DateTime projectDateAsOfMidnight = new DateTime(this.view.DateForProjection.Year, this.view.DateForProjection.Month, this.view.DateForProjection.Day);
- this.view.ProjectedBalance = String.Empty;
- this.PopulateGraph();
- if (projectDateAsOfMidnight >= this.allDaysInARangeForGraph[0].Date && projectDateAsOfMidnight <= this.allDaysInARangeForGraph[this.allDaysInARangeForGraph.Count - 1].Date)
- {
- TimeSpan span = projectDateAsOfMidnight - this.allDaysInARangeForGraph[0].Date;
- int index = span.Days;
- this.view.ProjectedBalance = this.allDaysInARangeForGraph[index].EndOfDayBalance.ToString(CultureInfo.CurrentCulture);
- }
- else
- {
- TimeSpan span = projectDateAsOfMidnight - this.view.AsOfDay.Date;
- BindingList<CalendarDay> fromAsOfDayUntilProjectionDate = new BindingList<CalendarDay>();
- this.GenerateDayRangeOfPayments(this.view.AsOfDay.Date, span.Days + 1, fromAsOfDayUntilProjectionDate);
- this.view.ProjectedBalance = fromAsOfDayUntilProjectionDate[span.Days].EndOfDayBalance.ToString(CultureInfo.CurrentCulture);
- }
-
- this.UpdateUpcomingPaymentsBalances();
- this.view.UpcomingPayments = this.upcomingPayments;
- }
-
- /// <summary>
- /// Handles the DeleteClicked event of the view control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
- private void OnDeleteClicked(object sender, EventArgs e)
- {
- this.Controller.DeleteCurrentPayment();
- }
-
- /// <summary>
- /// Handles the ListChanged event of the controller control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
- private void OnControllerListChanged(object sender, EventArgs e)
- {
- this.LoadViewOnModel();
- }
-
- /// <summary>
- /// Called when a scheduled payment is changed or added.
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The <see cref="BillsPresentation.ScheduledPaymentChangedEventArgs"/> instance containing the event data.</param>
- private void OnScheduledPaymentChanged(object sender, ScheduledPaymentChangedEventArgs e)
- {
- this.Controller.SetScheduledPayment(e.SelectedPayment.ScheduledPaymentId);
- }
-
- /// <summary>
- /// Handles the FormClosing event of the view control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
- private void OnFormClosing(object sender, EventArgs e)
- {
- this.Controller.SaveData();
- }
-
- /// <summary>
- /// Called when the as of date is changed.
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
- private void OnAsOfDateChanged(object sender, EventArgs e)
- {
- this.LoadViewOnModel();
- }
-
- /// <summary>
- /// Populates the graph.
- /// </summary>
- private void PopulateGraph()
- {
- this.GenerateDayRangeOfPayments(this.view.AsOfDay, 90, this.allDaysInARangeForGraph);
- this.view.DaysAndBalances = this.allDaysInARangeForGraph;
- }
-
- /// <summary>
- /// Generates the upcoming payments.
- /// </summary>
- private void GenerateUpcomingPayments()
- {
- this.upcomingPayments.Clear();
- foreach (ScheduledPayment scheduledPayment in this.Controller.BetterScheduledPayments)
- {
- if (scheduledPayment.PaymentRecurrence == Recurrence.None && scheduledPayment.FirstDate < this.view.AsOfDay)
- {
- continue;
- }
-
- this.upcomingPayments.Add(new PaymentWithDate()
- {
- Amount = scheduledPayment.Amount * (scheduledPayment.IsDebit ? -1 : 1),
- IsDebit = String.CompareOrdinal(scheduledPayment.PaymentType.Name, PaymentType.Debit.Name) == 0,
- Payee = scheduledPayment.Payee,
- ScheduledPaymentId = scheduledPayment.Id,
- PaymentDate = CalculateNextPaymentDate(this.view.AsOfDay, scheduledPayment),
- IncludeInProjection = scheduledPayment.IncludeInProjection
- });
-
- }
-
- this.upcomingPayments.Sort();
- this.UpdateUpcomingPaymentsBalances();
- }
-
- /// <summary>
- /// Updates the upcoming payments balances.
- /// </summary>
- private void UpdateUpcomingPaymentsBalances()
- {
- decimal currentBalance = this.view.CurrentBalance ?? 0;
- int i = 0;
- foreach (PaymentWithDate paymentOnDate in this.upcomingPayments)
- {
- if (paymentOnDate.IncludeInProjection)
- {
- currentBalance = currentBalance + paymentOnDate.Amount;
- }
-
- paymentOnDate.Balance = currentBalance;
- this.upcomingPayments.ResetItem(i);
- i++;
- }
- }
-
- /// <summary>
- /// Generates the day range of payments.
- /// </summary>
- /// <param name="startDate">The start date.</param>
- /// <param name="numberOfDaysToProject">The number of days to project.</param>
- /// <param name="output">The output.</param>
- private void GenerateDayRangeOfPayments(DateTime startDate, int numberOfDaysToProject, BindingList<CalendarDay> output)
- {
- output.Clear();
- decimal currentBalance = this.view.CurrentBalance ?? 0;
- for (int i = 0; i < numberOfDaysToProject; i++)
- {
- DateTime currentDate = startDate.AddDays(i).Date;
- CalendarDay currentCalendarDay = new CalendarDay() { Date = currentDate };
- output.Add(currentCalendarDay);
- currentCalendarDay.EndOfDayBalance = currentBalance;
- foreach (ScheduledPayment scheduledPayment in this.Controller.BetterScheduledPayments)
- {
- if (scheduledPayment.PaymentRecurrence == Recurrence.None && scheduledPayment.FirstDate != currentDate)
- {
- continue;
- }
-
- if (CalculateNextPaymentDate(currentDate, scheduledPayment) == currentDate)
- {
- currentCalendarDay.Payments.Add(new Payment()
- {
- Amount = scheduledPayment.Amount * (scheduledPayment.IsDebit ? -1 : 1),
- IsDebit = String.CompareOrdinal(scheduledPayment.PaymentType.Name, PaymentType.Debit.Name) == 0,
- Payee = scheduledPayment.Payee,
- ScheduledPaymentId = scheduledPayment.Id,
- IncludeInProjection = scheduledPayment.IncludeInProjection
- });
-
- if (scheduledPayment.IncludeInProjection)
- {
- if (scheduledPayment.IsDebit)
- {
- currentCalendarDay.EndOfDayBalance = currentCalendarDay.EndOfDayBalance - scheduledPayment.Amount;
- }
- else
- {
- currentCalendarDay.EndOfDayBalance = currentCalendarDay.EndOfDayBalance + scheduledPayment.Amount;
- }
- }
- }
- }
-
- currentCalendarDay.Payments.Sort();
- currentBalance = currentCalendarDay.EndOfDayBalance;
- }
- }
-
- /// <summary>
- /// Populates the calendar.
- /// </summary>
- private void PopulateCalendar()
- {
- this.GenerateDayRangeOfPayments(this.view.DayOnCalendar.AddMonths(-2), 180, this.allDaysInARangeForCalendar);
- BindingList<CalendarDay> datesWithPayments = new BindingList<CalendarDay>();
- foreach (CalendarDay item in allDaysInARangeForCalendar)
- {
- if (item.Payments.Count > 0)
- {
- datesWithPayments.Add(item);
- }
- }
-
- this.view.DatesWithPayments = datesWithPayments;
- }
-
- /// <summary>
- /// Loads the view on model.
- /// </summary>
- private void LoadViewOnModel()
- {
- this.Controller.LoadData();
-
- this.GenerateUpcomingPayments();
-
- this.PopulateGraph();
- this.PopulateCalendar();
- this.view.UpcomingPayments = this.upcomingPayments;
- this.OnSpecificDateSelected(this, new DateSelectedEventArgs() { SelectedDate = this.view.DayOnCalendar });
- }
-
- /// <summary>
- /// Handles the Load event of the view control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
- private void view_Load(object sender, EventArgs e)
- {
- this.view.AsOfDay = DateTime.Today;
- LoadViewOnModel();
- }
-
- /// <summary>
- /// Calculates the next payment date.
- /// </summary>
- /// <param name="asOfDate">As of date.</param>
- /// <param name="scheduledPayment">The scheduled payment.</param>
- /// <returns></returns>
- private static DateTime CalculateNextPaymentDate(DateTime asOfDate, ScheduledPayment scheduledPayment)
- {
- DateTime result = scheduledPayment.FirstDate;
- DateTime asOfDateAtMidnight = new DateTime(asOfDate.Year, asOfDate.Month, asOfDate.Day);
- if (scheduledPayment.PaymentRecurrence == Recurrence.Biweekly)
- {
- while (result < asOfDateAtMidnight)
- {
- result = result.AddDays(14);
- }
- }
- else if (scheduledPayment.PaymentRecurrence == Recurrence.Bimonthly)
- {
- while (result < asOfDateAtMidnight)
- {
- result = result.AddMonths(2);
- }
- }
- else if (scheduledPayment.PaymentRecurrence == Recurrence.Monthly)
- {
- while (result < asOfDateAtMidnight)
- {
- result = result.AddMonths(1);
- }
- }
- else if (scheduledPayment.PaymentRecurrence == Recurrence.Weekly)
- {
- while (result < asOfDateAtMidnight)
- {
- result = result.AddDays(7);
- }
- }
-
- return result;
- }
- }
- }