public static GoalMonthInfo CalculateGoalMonthInfo(Goal goal, DateTime month, List <Transaction> transactions) { var info = new GoalMonthInfo(); CalculateIdeal(transactions, goal, month, info); CalculateActual(transactions, month, info); CalculateStatus(goal, month, info); return(info); }
private static void CalculateStatus(Goal goal, DateTime month, GoalMonthInfo info) { var marginLimit = goal.Limit - (info.InitialAmount - goal.Limit) * 0.1; // 10% fail margin 10% if (DateTime.Now.Date > month.LastDayOfMonth()) // old month { info.Status = info.CurrentAmount >= goal.Limit ? GoalStatus.Success: (info.CurrentAmount < marginLimit ? GoalStatus.Failed : GoalStatus.OffTrack); } else // current month { info.Status = info.CurrentAmount < marginLimit ? GoalStatus.Failed : info.CurrentAmount < goal.Limit ? GoalStatus.OffTrack : info.CurrentAmount < info.CurrentIdealAmount ? GoalStatus.OffTrack : GoalStatus.OnTrack; } }
private static void CalculateActual(List <Transaction> transactions, DateTime month, GoalMonthInfo info) { var points = new List <DateAmountPoint>(); var date = month.FirstDayOfMonth(); var lastDate = (DateTime.Now.Date < month.LastDayOfMonth()) ? DateTime.Now.Date : month.LastDayOfMonth(); var cumulativeAmount = 0d; while (date <= lastDate) { var dayAmount = transactions.Where(x => x.Date.Date == date).Select(x => x.Amount).Sum(); cumulativeAmount += dayAmount; points.Add(new DateAmountPoint(date, cumulativeAmount)); date = date.AddDays(1); } info.CurrentAmount = cumulativeAmount; info.ActualPoints = points; }
private static void CalculateIdeal(List <Transaction> transactions, Goal goal, DateTime month, GoalMonthInfo info) { info.InitialAmount = transactions.Where(x => x.Recurring || x.Category.CategoryType == CategoryType.Recurring).Select(x => x.Amount).Sum(); var endAmount = goal.Limit; var startDate = month.FirstDayOfMonth(); var endDate = month.LastDayOfMonth(); var slope = (endAmount - info.InitialAmount) / (endDate.Subtract(startDate).Days + 1); // +1: initialAmount applies at start of day 1 (so actually at day 0) var points = new List <DateAmountPoint> { new DateAmountPoint(startDate, info.InitialAmount + slope), new DateAmountPoint(endDate, endAmount) }; var currentDate = DateTime.Now.Date; if (currentDate < endDate && currentDate > startDate) { var currentAmount = info.InitialAmount + (currentDate.Subtract(startDate).Days + 1) * slope; points.Add(new DateAmountPoint(currentDate, currentAmount)); info.CurrentIdealAmount = currentAmount; } else { info.CurrentIdealAmount = endAmount; } info.IdealPoints = points; }