using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using EnVisage.Models;
using System.Web.Mvc;
namespace EnVisage.Code.BLL
{
///
/// Provides ability to manage fiscal calendar.
///
public class FiscalCalendarManager : IDisposable
{
#region Constructors
private readonly EnVisageEntities _dbContext;
private readonly bool _isContexLocal = false;
public FiscalCalendarManager(EnVisageEntities dbContext = null)
{
if (dbContext == null)
{
_dbContext = new EnVisageEntities();
_isContexLocal = true;
}
else
{
_dbContext = dbContext;
}
}
public void Dispose()
{
if (_isContexLocal)
_dbContext.Dispose();
}
#endregion
#region Fiscal Calendar Settings
///
/// Returns Fiscal Calendar Settings records
///
/// Current time point to mark Active, Inactive and Future records
///
public FiscalCalendarListModel GetCalendarSettingsItems(DateTime timePoint)
{
bool activeItemSet = false;
DateTime validTimePoint = timePoint.Date;
FiscalCalendarListModel result = new FiscalCalendarListModel();
List items =
(from FiscalCalendarSetting rec in _dbContext.FiscalCalendarSettings
orderby rec.EffectiveChangeDate descending
where true
select rec).Take(10).ToList();
for (int index = 0; index < items.Count; index++)
{
FiscalCalendarModel currentItem = (FiscalCalendarModel)items[index];
result.Items.Add(currentItem);
if (currentItem.EffectiveChangeDate.HasValue && (currentItem.EffectiveChangeDate.Value > validTimePoint))
{
currentItem.Status = FiscalCalendarModel.FiscalCalendarSettingStatus.Future;
}
else
{
if (!activeItemSet)
{
currentItem.Status = FiscalCalendarModel.FiscalCalendarSettingStatus.Active;
activeItemSet = true;
}
else
{
currentItem.Status = FiscalCalendarModel.FiscalCalendarSettingStatus.Inactive;
}
}
}
return result;
}
public FiscalCalendarModel GetCalendarSettingsItem(Guid? id)
{
if (!id.HasValue || id.Value == Guid.Empty)
return null;
var record = _dbContext.FiscalCalendarSettings.Find(id.Value);
var result = (FiscalCalendarModel)record;
return result;
}
public static IEnumerable GetCalendarTypes()
{
return new List
{
new SelectListItem
{
Text = FiscalCalendarModel.FiscalCalendarType.CalendarYear.ToDisplayValue(),
Value = FiscalCalendarModel.FiscalCalendarType.CalendarYear.ToString()
},
new SelectListItem
{
Text = FiscalCalendarModel.FiscalCalendarType.Calendar445.ToDisplayValue(),
Value = FiscalCalendarModel.FiscalCalendarType.Calendar445.ToString()
},
new SelectListItem
{
Text = FiscalCalendarModel.FiscalCalendarType.Calendar454.ToDisplayValue(),
Value = FiscalCalendarModel.FiscalCalendarType.Calendar454.ToString()
},
new SelectListItem
{
Text = FiscalCalendarModel.FiscalCalendarType.Calendar544.ToDisplayValue(),
Value = FiscalCalendarModel.FiscalCalendarType.Calendar544.ToString()
},
};
}
public static IEnumerable GetWeekendings()
{
return new List
{
new SelectListItem
{
Text = DayOfWeek.Sunday.ToDisplayValue(),
Value = DayOfWeek.Sunday.ToString()
},
new SelectListItem
{
Text = DayOfWeek.Monday.ToDisplayValue(),
Value = DayOfWeek.Monday.ToString()
},
new SelectListItem
{
Text = DayOfWeek.Tuesday.ToDisplayValue(),
Value = DayOfWeek.Tuesday.ToString()
},
new SelectListItem
{
Text = DayOfWeek.Wednesday.ToDisplayValue(),
Value = DayOfWeek.Wednesday.ToString()
},
new SelectListItem
{
Text = DayOfWeek.Thursday.ToDisplayValue(),
Value = DayOfWeek.Thursday.ToString()
},
new SelectListItem
{
Text = DayOfWeek.Friday.ToDisplayValue(),
Value = DayOfWeek.Friday.ToString()
},
new SelectListItem
{
Text = DayOfWeek.Saturday.ToDisplayValue(),
Value = DayOfWeek.Saturday.ToString()
},
};
}
public static IEnumerable GetYearTypes()
{
return new List
{
new SelectListItem
{
Text = FiscalCalendarModel.CalendarYearType.StandardYear.ToDisplayValue(),
Value = FiscalCalendarModel.CalendarYearType.StandardYear.ToString()
},
new SelectListItem
{
Text = FiscalCalendarModel.CalendarYearType.Only52Weeks.ToDisplayValue(),
Value = FiscalCalendarModel.CalendarYearType.Only52Weeks.ToString()
},
new SelectListItem
{
Text = FiscalCalendarModel.CalendarYearType.LastWeekDay.ToDisplayValue(),
Value = FiscalCalendarModel.CalendarYearType.LastWeekDay.ToString()
},
};
}
public void SaveFiscalCalendarSettings(FiscalCalendarModel model, DateTime timePoint)
{
if (model == null)
throw new ArgumentNullException("model");
DateTime validTimePoint = timePoint.Date;
FiscalCalendarSetting itemToSave = new FiscalCalendarSetting();
FiscalCalendarModel activeItem = this.GetActiveCalendarSettingsItem(validTimePoint);
if (activeItem != null)
{
// If pending to activation calendar setting exist, we should remove them
this.RemoveFutureCalendarSettingsItems(validTimePoint);
if (activeItem.EffectiveChangeDate.HasValue && model.EffectiveChangeDate.HasValue &&
(activeItem.EffectiveChangeDate.Value == model.EffectiveChangeDate.Value))
{
// Remove active item, because new item has the same EffStartDate as Active one
this.RemoveCalendarSettingsItem(activeItem.Id);
}
}
// Create new calendar settings
model.CopyTo(itemToSave);
itemToSave.Id = Guid.NewGuid();
_dbContext.FiscalCalendarSettings.Add(itemToSave);
}
///
/// Returns active Fiscal Calendar record for given time point
///
///
///
public FiscalCalendarModel GetActiveCalendarSettingsItem(DateTime timePoint)
{
DateTime validTimePoint = timePoint.Date;
FiscalCalendarSetting rec =
(from FiscalCalendarSetting item in _dbContext.FiscalCalendarSettings
orderby item.EffectiveChangeDate descending
where item.EffectiveChangeDate <= validTimePoint
select item)
.FirstOrDefault();
FiscalCalendarModel result = (FiscalCalendarModel)rec;
if (result != null)
{
// Set status for record. We get active record for the timePoint, so status should be Active
result.Status = FiscalCalendarModel.FiscalCalendarSettingStatus.Active;
FiscalCalendarSetting nextRec =
(from FiscalCalendarSetting item in _dbContext.FiscalCalendarSettings
orderby item.EffectiveChangeDate ascending
where item.EffectiveChangeDate > validTimePoint
select item)
.FirstOrDefault();
if (nextRec != null)
result.ValidTo = nextRec.EffectiveChangeDate.AddDays(-1);
}
return result;
}
///
/// Removes all future Fiscal Calendar records relative to given time point
///
///
protected void RemoveFutureCalendarSettingsItems(DateTime timePoint)
{
var itemsToRemove = _dbContext.FiscalCalendarSettings.Where(t => t.EffectiveChangeDate > timePoint);
if (itemsToRemove.Count() > 0)
_dbContext.FiscalCalendarSettings.RemoveRange(itemsToRemove);
}
protected void RemoveCalendarSettingsItem(Guid id)
{
var foundItems = _dbContext.FiscalCalendarSettings.Where(t => t.Id.Equals(id));
if (foundItems.Count() > 0)
_dbContext.FiscalCalendarSettings.RemoveRange(foundItems);
}
#endregion
#region Pended to remove (after implementation of in-memory calendar)
//[Obsolete]
//public void UpdateFiscalCalendars(FiscalCalendarModel model)
//{
// switch (model.Type)
// {
// case FiscalCalendarModel.FiscalCalendarType.Calendar445:
// case FiscalCalendarModel.FiscalCalendarType.Calendar454:
// case FiscalCalendarModel.FiscalCalendarType.Calendar544:
// Apply445Year(model);
// break;
// default:
// ApplyCalendarYear(model);
// break;
// }
//}
/////
///// Generate fiscal calendar periods by the Calendar Year algo. 52 weeks in the year. Last 1-2 days will be be adjusted.
/////
/////
//private void ApplyCalendarYear(FiscalCalendarModel model)
//{
// var startDate = model.CurrentYearStartDate ?? DateTime.Today;
// var periodEndDate = startDate.AddYears(Settings.Default.GenerateCalendarYears);
// var weekEndDate = startDate.AddDays(6);
// var weeksList = new List(periodEndDate.Subtract(startDate).Days / 7); // approx number of weeks
// var monthList = new List(periodEndDate.Subtract(startDate).Days / 30); // approx number of months
// var quarterList = new List(periodEndDate.Subtract(startDate).Days / 91); // approx number of quarters
// var yearList = new List(Settings.Default.GenerateCalendarYears);
// FiscalCalendar prevWeek = null;
// //FiscalCalendar prevMonth = null; // SA. Commented because are unused. Compliller show warnings
// //FiscalCalendar prevQuarter = null;
// //FiscalCalendar prevYear = null;
// #region Load one latest record of each period type before startDate
// #endregion
// #region Create adjustment between last enddate from loaded record and startDate
// #endregion
// #region Generate records from startDate to periodEndDate
// int weekPeriodInt = 1, monthWeekNum = 1, monthNum = 1, quarterNum = 1;
// while (weekEndDate < periodEndDate)
// {
// #region Create a new year if new week is in the new calendar year
// var year = yearList.LastOrDefault();
// if (year == null || year.EndDate < weekEndDate)
// {
// year = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = Constants.FISCAL_YEAR_NAME_TEMPLATE,
// Type = (int)FiscalCalendarModel.FiscalYearType.Year,
// YearInt = weekEndDate.Year,
// QuarterInt = 4,
// PeriodInt = 1,
// StartDate = new DateTime(weekEndDate.Year, 1, 1),
// EndDate = new DateTime(weekEndDate.Year, 12, 31),
// SystemName = string.Format(Constants.FISCAL_YEAR_SYSTEMNAME_TEMPLATE, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// yearList.Add(year);
// quarterNum = 1; // reset quarter of the year number
// monthNum = 1; // reset month of the year number;
// weekPeriodInt = 1; // reset week of the year number;
// }
// #endregion
// #region Create a new quarter if new week is in the new quarter
// var quarter = quarterList.LastOrDefault();
// if (quarter == null || quarter.EndDate < weekEndDate)
// {
// quarter = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_QUARTER_NAME_TEMPLATE, quarterNum),
// Type = (int)FiscalCalendarModel.FiscalYearType.Quarter,
// YearInt = year.YearInt,
// QuarterInt = quarterNum,
// PeriodInt = quarterNum,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = ((prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1)).AddDays(90),// add 7 days * 13 weeks in quarter = 91 days
// SystemName = string.Format(Constants.FISCAL_QUARTER_SYSTEMNAME_TEMPLATE, quarterNum, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// if (quarterNum == 4)
// quarter.EndDate = new DateTime(quarter.EndDate.Year, 12, 31);
// quarterList.Add(quarter);
// quarterNum++;
// }
// #endregion
// #region Create a new month if new week is in the new month
// var month = monthList.LastOrDefault();
// if (month == null || month.EndDate < weekEndDate)
// {
// month = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_MONTH_NAME_TEMPLATE, weekEndDate.ToString("MMM").ToUpper()),
// Type = (int)FiscalCalendarModel.FiscalYearType.Month,
// YearInt = year.YearInt,
// QuarterInt = quarterNum - 1,
// PeriodInt = monthNum,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = ((prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1)).AddDays(27),// add 7 days * 4 weeks in month = 28 days
// SystemName = string.Format(Constants.FISCAL_MONTH_SYSTEMNAME_TEMPLATE, weekEndDate.ToString("MMM").ToUpper(), (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// // add 5th week to the 1st month of the quarter
// if (monthNum % 3 == 0)
// {
// month.EndDate = month.EndDate.AddDays(7);
// }
// // if we can place a 14th quarter week before 1st of January of next year then place it into the last quarter
// if (quarter.QuarterInt == 4 && month.PeriodInt == 12)
// month.EndDate = new DateTime(month.EndDate.Year, 12, 31);
// monthList.Add(month);
// monthNum++;
// monthWeekNum = 1; // reset week of the month number
// }
// #endregion
// // create a new week record
// var week = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_WEEK_NAME_TEMPLATE, month.Name.ToUpper(), monthWeekNum),
// Type = (int)FiscalCalendarModel.FiscalYearType.Week,
// YearInt = year.YearInt,
// QuarterInt = quarterNum - 1,
// PeriodInt = weekPeriodInt,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = weekEndDate,
// SystemName = string.Format(Constants.FISCAL_WEEK_SYSTEMNAME_TEMPLATE, month.Name.ToUpper(), monthWeekNum, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// weeksList.Add(week);
// // adjust remaining 1-2 days at the end of the year
// if (week.PeriodInt == 52)
// {
// monthWeekNum++;
// weekPeriodInt++;
// week = new FiscalCalendar()
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_WEEK_NAME_TEMPLATE, month.Name.ToUpper(), monthWeekNum),
// Type = (int)FiscalCalendarModel.FiscalYearType.Week,
// YearInt = year.YearInt,
// QuarterInt = quarterNum - 1,
// PeriodInt = weekPeriodInt,
// StartDate = week.EndDate.AddDays(1),
// EndDate = new DateTime(week.EndDate.Year, 12, 31),
// SystemName = string.Format(Constants.FISCAL_WEEK_SYSTEMNAME_TEMPLATE, month.Name.ToUpper(), monthWeekNum, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 1
// };
// weeksList.Add(week);
// }
// monthWeekNum++;
// weekPeriodInt++;
// prevWeek = week;
// weekEndDate = week.EndDate.AddDays(7);
// }
// #endregion
// #region Save generated fiscal periods to the DB
// foreach (var FiscalCalendar in yearList)
// {
// _dbContext.FiscalCalendars.Add(FiscalCalendar);
// }
// foreach (var obj in quarterList)
// {
// _dbContext.FiscalCalendars.Add(obj);
// }
// foreach (var obj in monthList)
// {
// _dbContext.FiscalCalendars.Add(obj);
// }
// foreach (var obj in weeksList)
// {
// _dbContext.FiscalCalendars.Add(obj);
// }
// #endregion
//}
/////
///// Generate fiscal calendar periods by the 5-4-4 algo. 52/53 weeks in the year. 53rd weeks added only when it become a 7 day gap at the end of the year.
/////
/////
//private void Apply445Year(FiscalCalendarModel model)
//{
// var startDate = model.CurrentYearStartDate ?? DateTime.Today;
// var periodEndDate = startDate.AddYears(Settings.Default.GenerateCalendarYears);
// var weekEndDate = startDate.AddDays(6);
// var weeksList = new List(periodEndDate.Subtract(startDate).Days / 7); // approx number of weeks
// var monthList = new List(periodEndDate.Subtract(startDate).Days / 30); // approx number of months
// var quarterList = new List(periodEndDate.Subtract(startDate).Days / 91); // approx number of quarters
// var yearList = new List(Settings.Default.GenerateCalendarYears);
// FiscalCalendar prevWeek = null;
// //FiscalCalendar prevMonth = null; // SA. Commented because are unused. Compiller shows warnings
// //FiscalCalendar prevQuarter = null;
// //FiscalCalendar prevYear = null;
// #region Load one latest record of each period type before startDate
// #endregion
// #region Create adjustment between last enddate from loaded record and startDate
// #endregion
// #region Generate records from startDate to periodEndDate
// //TODO: initial version, maybe required some refactoring
// int weekPeriodInt = 1, monthWeekNum = 1, monthNum = 1, quarterNum = 1;
// var isAddExtraWeek = false;
// while (weekEndDate < periodEndDate)
// {
// #region Create a new year if new week is in the new calendar year
// var year = yearList.LastOrDefault();
// if (year == null || year.EndDate < weekEndDate)
// {
// year = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = Constants.FISCAL_YEAR_NAME_TEMPLATE,
// Type = (int)FiscalCalendarModel.FiscalYearType.Year,
// YearInt = weekEndDate.Year,
// QuarterInt = 4,
// PeriodInt = 1,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = ((prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1)).AddDays(363),// add 7 days * 52 weeks in year = 364 days
// SystemName = string.Format(Constants.FISCAL_YEAR_SYSTEMNAME_TEMPLATE, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// // if we can place a 53rd week before 1st of January of next year then do it
// isAddExtraWeek = year.EndDate.AddDays(7) < new DateTime(weekEndDate.Year + 1, startDate.Month, startDate.Day);
// if (isAddExtraWeek)
// year.EndDate = year.EndDate.AddDays(7);
// yearList.Add(year);
// quarterNum = 1; // reset quarter of the year number
// monthNum = 1; // reset month of the year number;
// weekPeriodInt = 1; // reset week of the year number;
// }
// #endregion
// #region Create a new quarter if new week is in the new quarter
// var quarter = quarterList.LastOrDefault();
// if (quarter == null || quarter.EndDate < weekEndDate)
// {
// quarter = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_QUARTER_NAME_TEMPLATE, quarterNum),
// Type = (int)FiscalCalendarModel.FiscalYearType.Quarter,
// YearInt = year.YearInt,
// QuarterInt = quarterNum,
// PeriodInt = quarterNum,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = ((prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1)).AddDays(90),// add 7 days * 13 weeks in quarter = 91 days
// SystemName = string.Format(Constants.FISCAL_QUARTER_SYSTEMNAME_TEMPLATE, quarterNum, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// // if we can place a 14th week before 1st of January of next year then place it into the last quarter
// if (isAddExtraWeek && quarterNum == 4)
// quarter.EndDate = quarter.EndDate.AddDays(7);
// quarterList.Add(quarter);
// quarterNum++;
// }
// #endregion
// #region Create a new month if new week is in the new month
// var month = monthList.LastOrDefault();
// if (month == null || month.EndDate < weekEndDate)
// {
// month = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_MONTH_NAME_TEMPLATE, weekEndDate.ToString("MMM").ToUpper()),
// Type = (int)FiscalCalendarModel.FiscalYearType.Month,
// YearInt = year.YearInt,
// QuarterInt = quarterNum - 1,
// PeriodInt = monthNum,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = ((prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1)).AddDays(27),// add 7 days * 4 weeks in month = 28 days
// SystemName = string.Format(Constants.FISCAL_MONTH_SYSTEMNAME_TEMPLATE, weekEndDate.ToString("MMM").ToUpper(), (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// // add 5th week to the 1st month of the quarter
// if (monthNum % 3 == 1)
// {
// month.EndDate = month.EndDate.AddDays(7);
// }
// // if we can place a 14th quarter week before 1st of January of next year then place it into the last quarter
// if (isAddExtraWeek && quarter.QuarterInt == 4 && month.PeriodInt == 12)
// month.EndDate = month.EndDate.AddDays(7);
// monthList.Add(month);
// monthNum++;
// monthWeekNum = 1; // reset week of the month number
// }
// #endregion
// // create a new week record
// var week = new FiscalCalendar
// {
// Id = Guid.NewGuid(),
// Name = string.Format(Constants.FISCAL_WEEK_NAME_TEMPLATE, weekEndDate.ToString("MMM").ToUpper(), monthWeekNum),
// Type = (int)FiscalCalendarModel.FiscalYearType.Week,
// YearInt = year.YearInt,
// QuarterInt = quarterNum - 1,
// PeriodInt = weekPeriodInt,
// StartDate = (prevWeek == null) ? startDate : prevWeek.EndDate.AddDays(1),
// EndDate = weekEndDate,
// SystemName = string.Format(Constants.FISCAL_WEEK_SYSTEMNAME_TEMPLATE, weekEndDate.ToString("MMM").ToUpper(), monthWeekNum, (weekEndDate.Year % 100).ToString("00")),
// AdjustingPeriod = false,
// NonWorking = 0
// };
// weeksList.Add(week);
// monthWeekNum++;
// weekPeriodInt++;
// prevWeek = week;
// weekEndDate = weekEndDate.AddDays(7);
// }
// #endregion
// #region Save generated fiscal periods to the DB
// foreach (var FiscalCalendar in yearList)
// {
// _dbContext.FiscalCalendars.Add(FiscalCalendar);
// }
// foreach (var obj in quarterList)
// {
// _dbContext.FiscalCalendars.Add(obj);
// }
// foreach (var obj in monthList)
// {
// _dbContext.FiscalCalendars.Add(obj);
// }
// foreach (var obj in weeksList)
// {
// _dbContext.FiscalCalendars.Add(obj);
// }
// #endregion
//}
#endregion
#region Calendar methods for RMO (pended for refactoring)
public FiscalCalendar GetFirstWeek(DateTime? date = null)
{
var query = _dbContext.FiscalCalendars.AsNoTracking()
.Where(x => x.Type == (int)FiscalCalendarModel.FiscalYearType.Week && x.NonWorking == 0);
if (date.HasValue)
query = query.Where(x => x.EndDate >= date.Value);
return query.OrderBy(x => x.StartDate).FirstOrDefault();
}
public FiscalCalendar GetLastWeek()
{
var lastWeek = _dbContext.FiscalCalendars.AsNoTracking()
.Where(x => x.Type == (int)FiscalCalendarModel.FiscalYearType.Week && x.NonWorking == 0)
.OrderByDescending(x => x.EndDate)
.FirstOrDefault();
return lastWeek;
}
public List GetFiscalCalendar(FiscalCalendarModel.FiscalYearType type, DateTime? startDate, DateTime? endDate, bool onlyWorkingWeeks, bool? adjustingPeriod, bool includePartialWeeks)
{
return FilterWeeks(type, startDate, endDate, onlyWorkingWeeks, adjustingPeriod, includePartialWeeks).OrderBy(x => x.StartDate).ToList();
}
public List GetFiscalCalendar(FiscalCalendarModel.FiscalYearType type, List weeks, bool onlyWorkingWeeks, bool? adjustingPeriod, bool includePartialWeeks)
{
if (weeks == null || weeks.Count <= 0)
return new List();
var fc = FilterWeeks(type, null, null, onlyWorkingWeeks, adjustingPeriod, includePartialWeeks)
.Where(x => weeks.Contains(x.EndDate))
.OrderBy(x => x.StartDate)
.ToList();
return fc;
}
public Dictionary>> CastWeekEndingsToTree(List weekEndings)
{
var weekEndingsHierarchy = weekEndings.Select(x => new
{
x.Year,
x.Month,
x.Day
})
.GroupBy(x => x.Year)
.OrderBy(x => x.Key)
.ToDictionary(year => year.Key.ToString(),
months => months.GroupBy(month => month.Month)
.OrderBy(month => month.Key)
.ToDictionary(month => month.Key.ToString(),
days => days.Select(day => day.Day).OrderBy(day => day).ToList()));
return weekEndingsHierarchy;
}
private IQueryable FilterWeeks(FiscalCalendarModel.FiscalYearType type, DateTime? startDate, DateTime? endDate, bool onlyWorkingWeeks, bool? adjustingPeriod, bool includePartialWeeks)
{
var query = _dbContext.FiscalCalendars.AsNoTracking().Where(x => x.Type == (int)type && (!onlyWorkingWeeks || x.NonWorking == 0));
if (startDate.HasValue)
query = query.Where(x => x.EndDate >= startDate.Value);
if (endDate.HasValue)
{
// lets suppose endDate = 2017-01-31
if (includePartialWeeks) // in this case 2017-01-28 - 2017-02-03 will be the last week in the result
query = query.Where(x => x.StartDate <= endDate.Value);
else // in this case 2017-01-21 - 2017-01-27 will be the last week in the result
query = query.Where(x => x.EndDate <= endDate.Value);
}
if (onlyWorkingWeeks)
query = query.Where(x => x.NonWorking == 0);
if (adjustingPeriod.HasValue)
query = query.Where(x => x.AdjustingPeriod == adjustingPeriod);
return query;
}
#endregion
#region Holidays
///
/// Return total count for holidays (not versions, but groups count)
///
///
public int GetHolidaysCount()
{
int itemCount =
(from Holiday item in _dbContext.Holidays
select item.HolidayGroupId)
.Distinct()
.Count();
return itemCount;
}
public IEnumerable GetHolidays(DateTime timePoint)
{
DateTime validTimePoint = timePoint.Date;
var activeItemsEffectiveDates =
from item in
(from Holiday h in _dbContext.Holidays
where h.EffectiveChangeDate <= validTimePoint
select new
{
h.HolidayGroupId,
h.EffectiveChangeDate
})
group item by item.HolidayGroupId into g
select new
{
HolidayGroupId = g.Key,
EffectiveChangeDate = (from d in g select d.EffectiveChangeDate).Max()
};
// Get EffectiveChangeDate for the nearest future record in every Holiday
Dictionary activeItemsValidityDates =
(from item in
(from Holiday h in _dbContext.Holidays
where h.EffectiveChangeDate > validTimePoint
select new
{
HolidayGroupId = h.HolidayGroupId,
EffectiveChangeDate = h.EffectiveChangeDate
})
group item by item.HolidayGroupId into g
select new
{
HolidayGroupId = g.Key,
EffectiveChangeDate = (from d in g select d.EffectiveChangeDate).Min()
})
.ToDictionary(k => k.HolidayGroupId, v => v.EffectiveChangeDate);
// Build query for data to display
List srcData =
(from item in _dbContext.Holidays
join dt in activeItemsEffectiveDates on
new { item.HolidayGroupId, item.EffectiveChangeDate }
equals dt
select item).ToList();
List qry =
srcData.Select(t => (HolidayDisplayModel)(HolidayModel)t).ToList();
qry.ForEach(t => t.ValidTo = activeItemsValidityDates.Keys.Contains(t.HolidayGroupId) ?
activeItemsValidityDates[t.HolidayGroupId].AddDays(-1) : (DateTime?)null);
qry.ForEach(t => t.ValidToAsText = t.ValidTo.HasValue ?
t.ValidTo.Value.ToShortDateString() : String.Empty);
return qry;
}
///
/// Returns active Holiday record for given time point
///
///
public HolidayModel GetActiveHolidayItem(Guid holidayGroupId, DateTime timePoint)
{
DateTime validTimePoint = timePoint.Date;
Holiday rec =
(from Holiday item in _dbContext.Holidays
orderby item.EffectiveChangeDate descending
where item.HolidayGroupId.Equals(holidayGroupId) && (item.EffectiveChangeDate <= validTimePoint)
select item)
.FirstOrDefault();
var result = (HolidayModel)rec;
if (!result.MultipleDaysHoliday)
result.EndDate = null;
if (result.Id != Guid.Empty)
{
// Set status for record. We get active record for the timePoint, so status should be Active
result.Status = HolidayModel.HolidayStatus.Active;
Holiday nextRec =
(from Holiday item in _dbContext.Holidays
orderby item.EffectiveChangeDate ascending
where item.HolidayGroupId.Equals(holidayGroupId) && (item.EffectiveChangeDate > validTimePoint)
select item)
.FirstOrDefault();
if (nextRec != null)
result.ValidTo = nextRec.EffectiveChangeDate.AddDays(-1);
result.IncludexpenditureCategories = result.ExpenditureCategories != null && result.ExpenditureCategories.Count > 0;
}
return result;
}
///
/// Removes all future Holiday records relative to given time point
///
protected void RemoveFutureHolidayItems(Guid holidayGroupId, DateTime timePoint, Guid? exceptId = null)
{
var itemsToRemove = _dbContext.Holidays.Where(t =>
t.HolidayGroupId.Equals(holidayGroupId) && (t.EffectiveChangeDate > timePoint) &&
(!exceptId.HasValue || !t.Id.Equals(exceptId.Value)));
if (itemsToRemove.Count() > 0)
{
_dbContext.Holiday2Team.RemoveRange(itemsToRemove.SelectMany(x => x.Holiday2Team));
_dbContext.Holiday2PeopleResource.RemoveRange(itemsToRemove.SelectMany(x => x.Holiday2PeopleResource));
_dbContext.Holiday2ExpenditureCategory.RemoveRange(itemsToRemove.SelectMany(x => x.Holiday2ExpenditureCategory));
_dbContext.Holidays.RemoveRange(itemsToRemove);
}
}
protected void RemoveHolidayItem(Guid id)
{
var foundItems = _dbContext.Holidays.Where(t => t.Id.Equals(id));
if (foundItems.Count() > 0)
{
_dbContext.Holiday2Team.RemoveRange(foundItems.SelectMany(x => x.Holiday2Team));
_dbContext.Holiday2PeopleResource.RemoveRange(foundItems.SelectMany(x => x.Holiday2PeopleResource));
_dbContext.Holiday2ExpenditureCategory.RemoveRange(foundItems.SelectMany(x => x.Holiday2ExpenditureCategory));
_dbContext.Holidays.RemoveRange(foundItems);
}
}
public void SaveHoliday(HolidayModel model, DateTime timePoint)
{
if (model == null)
throw new ArgumentNullException("model");
// Create new holiday item (group of item versions)
var itemToSave = new Holiday();
model.CopyTo(itemToSave);
itemToSave.Id = Guid.NewGuid();
if (model.HolidayGroupId.Equals(Guid.Empty))
itemToSave.HolidayGroupId = Guid.NewGuid();
if (!model.CompanyImpactAllResources)
{
if (!model.IncludexpenditureCategories)
{
var holiday2PeopleResourceToAddCollection = new List();
foreach (var x in model.Resources)
{
var item = new Holiday2PeopleResource
{
Id = Guid.NewGuid(),
HolidayId = itemToSave.Id,
ResourceId = x
};
holiday2PeopleResourceToAddCollection.Add(item);
}
_dbContext.Holiday2PeopleResource.AddRange(holiday2PeopleResourceToAddCollection);
var holiday2TeamToAddCollection = new List();
foreach (var x in model.Teams)
{
var item = new Holiday2Team
{
Id = Guid.NewGuid(),
HolidayId = itemToSave.Id,
TeamId = x
};
holiday2TeamToAddCollection.Add(item);
}
_dbContext.Holiday2Team.AddRange(holiday2TeamToAddCollection);
_dbContext.Holiday2ExpenditureCategory.RemoveRange(itemToSave.Holiday2ExpenditureCategory);
}
else
{
var holiday2ExpenditureCategoryToAddCollection = new List();
foreach (var x in model.ExpenditureCategories)
{
var item = new Holiday2ExpenditureCategory
{
Id = Guid.NewGuid(),
HolidayId = itemToSave.Id,
ExpenditureCategoryId = x
};
holiday2ExpenditureCategoryToAddCollection.Add(item);
}
_dbContext.Holiday2ExpenditureCategory.AddRange(holiday2ExpenditureCategoryToAddCollection);
_dbContext.Holiday2Team.RemoveRange(itemToSave.Holiday2Team);
_dbContext.Holiday2PeopleResource.RemoveRange(itemToSave.Holiday2PeopleResource);
}
}
else
{
_dbContext.Holiday2Team.RemoveRange(itemToSave.Holiday2Team);
_dbContext.Holiday2PeopleResource.RemoveRange(itemToSave.Holiday2PeopleResource);
_dbContext.Holiday2ExpenditureCategory.RemoveRange(itemToSave.Holiday2ExpenditureCategory);
}
var validTimePoint = timePoint.Date;
HolidayModel activeItem = null;
if (!model.HolidayGroupId.Equals(Guid.Empty))
{
activeItem = this.GetActiveHolidayItem(model.HolidayGroupId, validTimePoint);
if ((activeItem != null) && !activeItem.Id.Equals(itemToSave.Id))
{
if (model.EffectiveChangeDate.HasValue)
// Remove holiday allocations
this.RemoveHolidayAllocations(model.HolidayGroupId, model.EffectiveChangeDate.Value);
}
else
activeItem = null;
}
_dbContext.BulkSaveChanges();
// Holiday Allocations generation
HolidayModel modelCopy = model.Clone();
modelCopy.Id = itemToSave.Id;
modelCopy.HolidayGroupId = itemToSave.HolidayGroupId;
this.CreateHolidayAllocations(modelCopy);
_dbContext.Holidays.Add(itemToSave);
_dbContext.SaveChanges();
if (!model.HolidayGroupId.Equals(Guid.Empty))
{
if (activeItem != null)
{
// If pended to activation calendar setting exist, we should remove them
this.RemoveFutureHolidayItems(model.HolidayGroupId, validTimePoint, itemToSave.Id);
if (activeItem.EffectiveChangeDate.HasValue && model.EffectiveChangeDate.HasValue &&
(activeItem.EffectiveChangeDate.Value == model.EffectiveChangeDate.Value))
{
// Remove active item, because new item has the same EffStartDate as Active one
this.RemoveHolidayItem(activeItem.Id);
}
}
}
}
///
/// Returns history records for Holiday
///
/// Current time point to mark Active, Inactive and Future records
///
public HolidayListModel GetHolidayHistoryItems(Guid holidayGroupId, DateTime timePoint)
{
bool activeItemSet = false;
DateTime validTimePoint = timePoint.Date;
HolidayListModel result = new HolidayListModel();
List items =
(from Holiday rec in _dbContext.Holidays
orderby rec.EffectiveChangeDate descending
where rec.HolidayGroupId.Equals(holidayGroupId)
select rec).Take(10).ToList();
for (int index = 0; index < items.Count; index++)
{
HolidayModel currentItem = (HolidayModel)items[index];
if (currentItem.EffectiveChangeDate.HasValue && (currentItem.EffectiveChangeDate.Value > validTimePoint))
{
currentItem.Status = HolidayModel.HolidayStatus.Future;
}
else
{
if (!activeItemSet)
{
currentItem.Status = HolidayModel.HolidayStatus.Active;
activeItemSet = true;
}
else
{
currentItem.Status = HolidayModel.HolidayStatus.Inactive;
}
}
HolidayDisplayModel currentDisplayItem = (HolidayDisplayModel)currentItem;
result.Items.Add(currentDisplayItem);
}
return result;
}
public void DeleteHoliday(Guid holidayGroupId)
{
var foundItems = _dbContext.Holidays.Where(t => t.HolidayGroupId.Equals(holidayGroupId));
if (foundItems.Count() < 1)
throw new Exception(String.Format("Holiday (holidayGroupId = '{0}') not found", holidayGroupId.ToString()));
_dbContext.Holiday2Team.RemoveRange(foundItems.SelectMany(x => x.Holiday2Team));
_dbContext.Holiday2PeopleResource.RemoveRange(foundItems.SelectMany(x => x.Holiday2PeopleResource));
_dbContext.Holiday2ExpenditureCategory.RemoveRange(foundItems.SelectMany(x => x.Holiday2ExpenditureCategory));
_dbContext.Holidays.RemoveRange(foundItems);
// Remove all holiday allocations for all its group of records
this.RemoveHolidayAllocations(holidayGroupId);
}
#endregion
#region Holiday Allocations
///
/// Removes all holiday allocation records for specified Holiday Group
///
protected void RemoveHolidayAllocations(Guid holidayGroupId)
{
var itemsToRemove = _dbContext.HolidayAllocations.Where(x => x.HolidayGroupId.Equals(holidayGroupId));
_dbContext.HolidayAllocations.RemoveRange(itemsToRemove);
}
///
/// Return date for start team membership (according to fiscal calendar) by specified date point
///
/// Source date point
///
///
public static DateTime GetDateForTeamMembershipStart(DateTime date, EnVisageEntities dbContext)
{
var fiscalWeeks = GetFiscalCalendarCurrentAndNextWeeksForDate(date, dbContext);
if (fiscalWeeks.Count > 0)
{
if (fiscalWeeks.First().StartDate == date)
return fiscalWeeks.First().StartDate;
if (fiscalWeeks.Count > 1)
return fiscalWeeks.Last().StartDate;
return Constants.FISCAL_CALENDAR_MAX_DATE;
}
string errMessage = "There are no full fiscal weeks for the specified date point: {0}";
throw new Exception(String.Format(errMessage, date.ToShortDateString()));
}
///
/// Return date for end team membership (according to fiscal calendar) by specified date point
///
/// Source date point
///
///
public static DateTime? GetDateForTeamMembershipEnd(DateTime date, EnVisageEntities dbContext)
{
var fiscalWeeks = GetFiscalCalendarCurrentAndPrevWeeksForDate(date, dbContext);
if (fiscalWeeks.Count > 0)
{
if (fiscalWeeks.First().EndDate == date)
return fiscalWeeks.First().EndDate;
if (fiscalWeeks.Count > 1)
return fiscalWeeks.Last().EndDate;
}
return null;
}
///
/// Removes holiday allocations for specified Holiday Group from specified time point and to the future
///
protected void RemoveHolidayAllocations(Guid holidayGroupId, DateTime startingPoint)
{
// Note:
// 1. We must find the week, startingPoint belongs to. Let's call it Updatable week.
// If Holiday allocations for this week exist, we should update this allocations record,
// because this record can share allocations for current holiday item and its previous version.
// 2. We must remove all the allocations, next to the Updatable week
// (they will be calculated and created againt, when the holiday item saved)
DateTime startDateCorrected = startingPoint.Date;
DateRange we = GetFiscalCalendarWeekForDate(startingPoint, _dbContext);
DateTime updatableWeekWe = we.EndDate;
// Get updatable allocations record
var updatableAllocRec =
_dbContext.HolidayAllocations.FirstOrDefault(x => x.HolidayGroupId.Equals(holidayGroupId) &&
(x.WeekEndingDate == updatableWeekWe));
if (updatableAllocRec != null)
{
// Allocation record for update found. Perform update
int daysAffected = Convert.ToInt32((updatableWeekWe - startDateCorrected).TotalDays) + 1;
for (int index = 0; index < daysAffected; index++)
{
DateTime currentDate = startDateCorrected.AddDays(index);
switch (currentDate.DayOfWeek)
{
case DayOfWeek.Sunday:
updatableAllocRec.Sunday = true;
break;
case DayOfWeek.Monday:
updatableAllocRec.Monday = true;
break;
case DayOfWeek.Tuesday:
updatableAllocRec.Tuesday = true;
break;
case DayOfWeek.Wednesday:
updatableAllocRec.Wednesday = true;
break;
case DayOfWeek.Thursday:
updatableAllocRec.Thursday = true;
break;
case DayOfWeek.Friday:
updatableAllocRec.Friday = true;
break;
case DayOfWeek.Saturday:
updatableAllocRec.Saturday = true;
break;
}
}
}
// Perform deleting of future allocation records
var recsToRemove = _dbContext.HolidayAllocations
.Where(x => x.HolidayGroupId.Equals(holidayGroupId) && (x.WeekEndingDate > updatableWeekWe));
_dbContext.HolidayAllocations.RemoveRange(recsToRemove);
}
///
/// Creates holiday allocations records for holiday
///
protected void CreateHolidayAllocations(HolidayModel model)
{
if (model.WorkingDays)
return;
// Get holiday days and corresponding weekendings in the Fiscal Calendar
List holidayDates = model.GetHolidayDates();
if (holidayDates.Count < 1)
return;
var weekendingsForDates = GetFiscalCalendarWeekendingsForDates(holidayDates);
var newAllocations = new List();
Dictionary allocationsForDates =
_dbContext.HolidayAllocations.Where(a => a.HolidayGroupId.Equals(model.HolidayGroupId) &&
weekendingsForDates.Values.Contains(a.WeekEndingDate)).
ToDictionary(k => k.WeekEndingDate, v => v);
foreach (DateTime holidayDate in holidayDates)
{
DateTime? we = weekendingsForDates[holidayDate];
if (we.HasValue)
{
HolidayAllocation ha = null;
if (allocationsForDates.ContainsKey(we.Value))
{
ha = allocationsForDates[we.Value];
ha.HolidayId = model.Id;
}
else
{
ha = new HolidayAllocation
{
Id = Guid.NewGuid(),
HolidayId = model.Id,
HolidayGroupId = model.HolidayGroupId,
WeekEndingDate = we.Value,
Sunday = true,
Monday = true,
Tuesday = true,
Wednesday = true,
Thursday = true,
Friday = true,
Saturday = true
};
newAllocations.Add(ha);
allocationsForDates[we.Value] = ha;
}
switch (holidayDate.DayOfWeek)
{
case DayOfWeek.Sunday:
ha.Sunday = false;
break;
case DayOfWeek.Monday:
ha.Monday = false;
break;
case DayOfWeek.Tuesday:
ha.Tuesday = false;
break;
case DayOfWeek.Wednesday:
ha.Wednesday = false;
break;
case DayOfWeek.Thursday:
ha.Thursday = false;
break;
case DayOfWeek.Friday:
ha.Friday = false;
break;
case DayOfWeek.Saturday:
ha.Saturday = false;
break;
}
}
}
_dbContext.HolidayAllocations.AddRange(newAllocations);
}
///
/// Gets weekly holiday allocations grouped by PeopleResourceId and then by weekending date.
///
/// A collection of people resource identifiers.
/// Start date of period to search.
/// End date of period to search.
/// A dictionary of dictionaries [PeopleResourceId, [Weekending, AdjustmentKoeff]]
public Dictionary> GetHolidayAllocationsByResource(DateTime? startDate, DateTime? endDate, IEnumerable resourceIds = null, IEnumerable teamIds = null)
{
if (endDate <= startDate)
return new Dictionary>();
var result = new Dictionary>();
var list = GetHolidayAllocations(startDate, endDate, resourceIds, teamIds);
foreach (var item in list.OrderBy(t => t.WeekEndingDate))
{
if (!result.ContainsKey(item.PeopleResourceId.Value))
result.Add(item.PeopleResourceId.Value, new Dictionary());
if (!result[item.PeopleResourceId.Value].ContainsKey(item.WeekEndingDate))
result[item.PeopleResourceId.Value].Add(item.WeekEndingDate, item.AdjustmentKoeff);
}
return result;
}
public IEnumerable GetHolidayAllocations(DateTime? startDate, DateTime? endDate, IEnumerable resourceIds = null, IEnumerable teamIds = null)
{
if (endDate <= startDate)
return new List();
var holidaysQuery = _dbContext.VW_HolidayAllocation.AsNoTracking().AsQueryable();
if (resourceIds != null && resourceIds.Any())
holidaysQuery = holidaysQuery.Where(t => t.PeopleResourceId.HasValue && resourceIds.Contains(t.PeopleResourceId.Value));
if (teamIds != null && teamIds.Any())
holidaysQuery = holidaysQuery.Where(t => t.TeamId.HasValue && teamIds.Contains(t.TeamId.Value));
if (startDate.HasValue)
holidaysQuery = holidaysQuery.Where(x => x.WeekEndingDate >= startDate);
if (endDate.HasValue)
holidaysQuery = holidaysQuery.Where(x => x.WeekEndingDate <= endDate);
return holidaysQuery.ToList();
}
#endregion
#region Get Weekendings Data methods
///
/// Return StartDate and EndDate for fiscal week containing specified date point
///
public static DateRange GetFiscalCalendarWeekForDate(DateTime date, EnVisageEntities dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
string errMessage;
DateTime dateCorrected = date.Date;
var weekending =
dbContext.FiscalCalendars
.Where(c => (c.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(c.StartDate <= dateCorrected) && (c.EndDate >= dateCorrected)).FirstOrDefault();
if (weekending == null)
{
errMessage = String.Format("No fiscal week, containing specified date found (date point: {0})",
date.ToShortDateString());
throw new Exception(errMessage);
}
return (DateRange)weekending;
}
///
/// Return StartDate and EndDate for previous fiscal week for the one, containing specified date point
///
public static DateRange GetFiscalCalendarPrevWeekForDate(DateTime date, EnVisageEntities dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
string errMessage;
DateTime dateCorrected = date.Date;
var weekendingsOrdered =
dbContext.FiscalCalendars.AsNoTracking()
.Where(c => (c.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(c.StartDate <= dateCorrected)).OrderByDescending(x => x.StartDate)
.Take(2).ToList();
if (weekendingsOrdered.Count < 2)
{
errMessage = String.Format("No previous fiscal week for the one, containing specified date found (date point: {0})",
date.ToShortDateString());
throw new Exception(errMessage);
}
return (DateRange)weekendingsOrdered.Last();
}
///
/// Returns current fiscal week (containing date point) and the previous one (1st = current, 2nd = prev)
///
public static List GetFiscalCalendarCurrentAndPrevWeeksForDate(DateTime date, EnVisageEntities dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DateTime dateCorrected = date.Date;
var weekendingsOrdered =
dbContext.FiscalCalendars.AsNoTracking()
.Where(c => (c.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(c.StartDate <= dateCorrected)).OrderByDescending(x => x.StartDate)
.Take(2).ToList();
List result = weekendingsOrdered.Select(x => (DateRange)x).ToList();
return result;
}
///
/// Returns current fiscal week (containing date point) and the next one (1st = current, 2nd = next)
///
public static List GetFiscalCalendarCurrentAndNextWeeksForDate(DateTime date, EnVisageEntities dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DateTime dateCorrected = date.Date;
var weekendingsOrdered =
dbContext.FiscalCalendars.AsNoTracking()
.Where(c => (c.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(c.EndDate >= dateCorrected)).OrderBy(x => x.StartDate)
.Take(2).ToList();
List result = weekendingsOrdered.Select(x => (DateRange)x).ToList();
return result;
}
///
/// Returns weekendings for the fiscal weeks containing specified dates. Result is the dictionary,
/// where keys are specified dates, and values are their corresponding weekendings
///
protected Dictionary GetFiscalCalendarWeekendingsForDates(List dates)
{
List datesCorrected = dates.Select(d => d.Date).OrderBy(d => d).ToList();
DateTime minDate = datesCorrected.First();
DateTime maxDate = datesCorrected.Last();
DateTime fcBrowseStartDate = minDate.AddMonths(-1);
DateTime fcBrowseEndDate = maxDate.AddMonths(1);
var weekendings =
_dbContext.FiscalCalendars
.Where(c => (c.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(c.StartDate >= fcBrowseStartDate) && (c.EndDate <= fcBrowseEndDate))
.Select(c => new { c.StartDate, c.EndDate }).ToList();
Dictionary couples = datesCorrected.Select(d =>
new KeyValuePair(d, weekendings
.Where(c => (c.StartDate <= d) && (c.EndDate >= d))
.Select(c => c.EndDate).FirstOrDefault())
).ToDictionary(k => k.Key, v =>
(v.Value.HasValue && v.Value != DateTime.MinValue) ? v.Value : (DateTime?)null);
return couples;
}
public static List GetWeekendingsByRange(DateTime startDate, DateTime? endDate, EnVisageEntities dbContext)
{
var weekendings =
dbContext.FiscalCalendars.AsNoTracking().Where(x => (x.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(x.EndDate >= startDate) && (!endDate.HasValue || (x.StartDate <= endDate.Value)) &&
(x.AdjustingPeriod == false))
.OrderBy(x => x.StartDate)
.Select(x => x.EndDate).ToList();
return weekendings;
}
///
/// Returns Fiscal Calendar Weeks (start & end dates) for specified date range
///
public static List GetFiscalCalendarWeeksByRange(DateTime startDate, DateTime? endDate, EnVisageEntities dbContext)
{
List result =
dbContext.FiscalCalendars.AsNoTracking().Where(x => (x.Type == (int)FiscalCalendarModel.FiscalYearType.Week) &&
(x.EndDate >= startDate) && (!endDate.HasValue || (x.StartDate <= endDate.Value)) &&
(x.AdjustingPeriod == false))
.OrderBy(x => x.StartDate).ToList()
.Select(x => (DateRange)x).ToList();
return result;
}
///
/// Returns StartDate for the earliest period of _type_ in fiscal calendar
///
/// Fiscal Calendar Type
///
public static DateTime GetCalendarMinDate(FiscalCalendarModel.FiscalYearType type = FiscalCalendarModel.FiscalYearType.Week)
{
using (var dbContext = new EnVisageEntities())
{
var result = dbContext.FiscalCalendars.Where(x => x.Type == (int)type).Select(x => x.StartDate).Min();
return result;
}
}
///
/// Returns EndDate for the latest period of _type_ in fiscal calendar
///
/// Fiscal Calendar Type
///
public static DateTime GetCalendarMaxDate(FiscalCalendarModel.FiscalYearType type = FiscalCalendarModel.FiscalYearType.Week)
{
using (var dbContext = new EnVisageEntities())
{
var result = dbContext.FiscalCalendars.Where(x => x.Type == (int)type).Select(x => x.EndDate).Max();
return result;
}
}
#endregion
}
///
/// Class for representing Date Ranges
///
public class DateRange
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public static explicit operator DateRange(DateRangeNullable obj)
{
if (obj == null)
return null;
if (!obj.StartDate.HasValue || !obj.EndDate.HasValue)
throw new InvalidCastException("DateRangeNullable can't be casted to DateRange because of null values");
var result = new DateRange()
{
StartDate = obj.StartDate.Value,
EndDate = obj.EndDate.Value
};
return result;
}
public static explicit operator DateRange(FiscalCalendar obj)
{
if (obj == null)
return null;
var result = new DateRange()
{
StartDate = obj.StartDate,
EndDate = obj.EndDate
};
return result;
}
}
///
/// Class for representing Date Ranges with nullable bounds
///
public class DateRangeNullable
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public static explicit operator DateRangeNullable(DateRange obj)
{
if (obj == null)
return null;
var result = new DateRangeNullable()
{
StartDate = obj.StartDate,
EndDate = obj.EndDate
};
return result;
}
// Returns True, if date fits the range
public bool IsInRange(DateTime date)
{
return (!StartDate.HasValue || (StartDate.HasValue && StartDate.Value <= date)) &&
(!EndDate.HasValue || (EndDate.HasValue && EndDate.Value >= date));
}
}
}