EnVisageOnline/Main-RMO/Source/EnVisage/Code/BLL/FiscalCalendarManager.cs

923 lines
33 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Globalization;
using System.Linq;
using EnVisage.Models;
using EnVisage.Properties;
using System.Web.Mvc;
namespace EnVisage.Code.BLL
{
/// <summary>
/// Provides ability to manage fiscal calendar.
/// </summary>
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
private DateTime GetValidTimePoint(DateTime srcDate)
{
return new DateTime(srcDate.Year, srcDate.Month, srcDate.Day);
}
/// <summary>
/// Returns Fiscal Calendar Settings records
/// </summary>
/// <param name="timePoint">Current time point to mark Active, Inactive and Future records</param>
/// <returns></returns>
public FiscalCalendarListModel GetCalendarSettingsItems(DateTime timePoint)
{
bool activeItemSet = false;
DateTime validTimePoint = GetValidTimePoint(timePoint);
FiscalCalendarListModel result = new FiscalCalendarListModel();
List<FiscalCalendarSetting> 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)
{
FiscalCalendarModel result = new FiscalCalendarModel();
if (id.HasValue && (id.Value != Guid.Empty))
{
var record = _dbContext.FiscalCalendarSettings.Find(id.Value);
if (record != null)
result = (FiscalCalendarModel)record;
}
return result;
}
public static IEnumerable<SelectListItem> GetCalendarTypes()
{
return new List<SelectListItem>
{
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<SelectListItem> GetWeekendings()
{
return new List<SelectListItem>
{
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<SelectListItem> GetYearTypes()
{
return new List<SelectListItem>
{
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 = GetValidTimePoint(timePoint);
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);
}
/// <summary>
/// Returns active Fiscal Calendar record for given time point
/// </summary>
/// <param name="timePoint"></param>
/// <returns></returns>
public FiscalCalendarModel GetActiveCalendarSettingsItem(DateTime timePoint)
{
DateTime validTimePoint = this.GetValidTimePoint(timePoint);
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;
}
/// <summary>
/// Removes all future Fiscal Calendar records relative to given time point
/// </summary>
/// <param name="timePoint"></param>
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;
// }
//}
///// <summary>
///// Generate fiscal calendar periods by the Calendar Year algo. 52 weeks in the year. Last 1-2 days will be be adjusted.
///// </summary>
///// <param name="model"></param>
//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<FiscalCalendar>(periodEndDate.Subtract(startDate).Days / 7); // approx number of weeks
// var monthList = new List<FiscalCalendar>(periodEndDate.Subtract(startDate).Days / 30); // approx number of months
// var quarterList = new List<FiscalCalendar>(periodEndDate.Subtract(startDate).Days / 91); // approx number of quarters
// var yearList = new List<FiscalCalendar>(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
//}
///// <summary>
///// 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.
///// </summary>
///// <param name="model"></param>
//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<FiscalCalendar>(periodEndDate.Subtract(startDate).Days / 7); // approx number of weeks
// var monthList = new List<FiscalCalendar>(periodEndDate.Subtract(startDate).Days / 30); // approx number of months
// var quarterList = new List<FiscalCalendar>(periodEndDate.Subtract(startDate).Days / 91); // approx number of quarters
// var yearList = new List<FiscalCalendar>(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 List<FiscalCalendar> GetFiscalCalendar(FiscalCalendarModel.FiscalYearType type, DateTime? startDate, DateTime? endDate, bool onlyWorkingWeeks, bool? adjustingPeriod)
{
return FilterWeeks(type, startDate, endDate, onlyWorkingWeeks, adjustingPeriod).OrderBy(x => x.StartDate).ToList();
}
private IQueryable<FiscalCalendar> FilterWeeks(FiscalCalendarModel.FiscalYearType type, DateTime? startDate, DateTime? endDate, bool onlyWorkingWeeks, bool? adjustingPeriod)
{
var query = _dbContext.FiscalCalendars.Where(x => x.Type == (int)type && (!onlyWorkingWeeks || x.NonWorking == 0));
if (startDate.HasValue)
query = query.Where(x => x.StartDate >= startDate.Value);
if (endDate.HasValue)
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;
}
//// SA. ??? Check usage of the method
//public List<DateTime> GetWeekEndings(FiscalCalendarModel.FiscalYearType type, DateTime startDate, DateTime endDate, bool onlyWorkingWeeks)
//{
// return _dbContext.FiscalCalendars.Where(x => x.Type == (int)type &&
// x.EndDate >= startDate &&
// x.EndDate <= endDate &&
// (!onlyWorkingWeeks || x.NonWorking == 0))
// .Select(x => x.EndDate).ToList();
//}
#endregion
#region Holidays
/// <summary>
/// Return total count for holidays (not versions, but groups count)
/// </summary>
/// <returns></returns>
public int GetHolidaysCount()
{
int itemCount =
(from Holiday item in _dbContext.Holidays
select item.HolidayId)
.Distinct()
.Count();
return itemCount;
}
public IEnumerable<HolidayDisplayModel> GetHolidays(DateTime timePoint)
{
DateTime validTimePoint = this.GetValidTimePoint(timePoint);
var activeItemsEffectiveDates =
(from item in
(from Holiday h in _dbContext.Holidays
where h.EffectiveChangeDate <= validTimePoint
select new
{
h.HolidayId,
h.EffectiveChangeDate
})
group item by item.HolidayId into g
select new
{
HolidayId = g.Key,
EffectiveChangeDate = (from d in g select d.EffectiveChangeDate).Max()
});
// Get EffectiveChangeDate for the nearest future record in every Holiday
Dictionary<Guid, DateTime> activeItemsValidityDates =
(from item in
(from Holiday h in _dbContext.Holidays
where h.EffectiveChangeDate > validTimePoint
select new
{
HolidayId = h.HolidayId,
EffectiveChangeDate = h.EffectiveChangeDate
})
group item by item.HolidayId into g
select new
{
HolidayId = g.Key,
EffectiveChangeDate = (from d in g select d.EffectiveChangeDate).Min()
})
.ToDictionary(k => k.HolidayId, v => v.EffectiveChangeDate);
// Build query for data to display
List<HolidayModel> srcData =
(from item in _dbContext.Holidays
join dt in activeItemsEffectiveDates on
new { item.HolidayId, item.EffectiveChangeDate }
equals dt
select new HolidayModel
{
Id = item.Id,
HolidayId = item.HolidayId,
Name = item.Name,
OccurrenceType = (HolidayModel.HolidayOccurrence)item.OccurrenceType,
OccurrenceMonth = item.OccurrenceMonth,
OccurrenceMonthDay = item.OccurrenceMonthDay,
OccurrenceWeekDay = (DayOfWeek)item.OccurrenceWeekDay,
NonWorkingWeek = item.NonWorkingWeek,
WorkingDay = item.WorkingDay,
EffectiveChangeDate = item.EffectiveChangeDate,
}).ToList();
List<HolidayDisplayModel> qry =
srcData.Select(t => new HolidayDisplayModel
{
Id = t.Id,
HolidayId = t.HolidayId,
Name = t.Name,
Date = HolidayModel.GetHolidayDate(t.OccurrenceType.Value, (short)t.OccurrenceMonth.Value,
(short)t.OccurrenceMonthDay.Value, (short)t.OccurrenceWeekDay.Value),
NonWorkingWeek = t.NonWorkingWeek,
WorkingDay = t.WorkingDay,
EffectiveChangeDate = t.EffectiveChangeDate.Value,
EffectiveChangeDateAsText = t.EffectiveChangeDate.Value.ToShortDateString(),
ValidTo = (activeItemsValidityDates.Keys.Contains(t.HolidayId) ? activeItemsValidityDates[t.HolidayId].AddDays(-1) : (DateTime?)null),
}).ToList();
qry.ForEach(t => t.DateText = t.Date.ToShortDateString());
qry.ForEach(t => t.ValidToAsText = t.ValidTo.HasValue ? t.ValidTo.Value.ToShortDateString() : String.Empty);
return qry;
}
/// <summary>
/// Returns active Holiday record for given time point
/// </summary>
/// <returns></returns>
public HolidayModel GetActiveHolidayItem(Guid holidayId, DateTime timePoint)
{
DateTime validTimePoint = this.GetValidTimePoint(timePoint);
Holiday rec =
(from Holiday item in _dbContext.Holidays
orderby item.EffectiveChangeDate descending
where item.HolidayId.Equals(holidayId) && (item.EffectiveChangeDate <= validTimePoint)
select item)
.FirstOrDefault();
HolidayModel result = (HolidayModel)rec;
if (result != null)
{
// 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.HolidayId.Equals(holidayId) && (item.EffectiveChangeDate > validTimePoint)
select item)
.FirstOrDefault();
if (nextRec != null)
result.ValidTo = nextRec.EffectiveChangeDate.AddDays(-1);
}
return result;
}
/// <summary>
/// Removes all future Holiday records relative to given time point
/// </summary>
protected void RemoveFutureHolidayItems(Guid holidayId, DateTime timePoint)
{
var itemsToRemove = _dbContext.Holidays.Where(t => t.HolidayId.Equals(holidayId) && (t.EffectiveChangeDate > timePoint));
if (itemsToRemove.Count() > 0)
_dbContext.Holidays.RemoveRange(itemsToRemove);
}
protected void RemoveHolidayItem(Guid id)
{
var foundItems = _dbContext.Holidays.Where(t => t.Id.Equals(id));
if (foundItems.Count() > 0)
_dbContext.Holidays.RemoveRange(foundItems);
}
public void SaveHoliday(HolidayModel model, DateTime timePoint)
{
if (model == null)
throw new ArgumentNullException("model");
DateTime validTimePoint = GetValidTimePoint(timePoint);
Holiday itemToSave = new Holiday();
if (!model.HolidayId.Equals(Guid.Empty))
{
HolidayModel activeItem = this.GetActiveHolidayItem(model.HolidayId, validTimePoint);
if (activeItem != null)
{
// If pended to activation calendar setting exist, we should remove them
this.RemoveFutureHolidayItems(model.HolidayId, 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.RemoveHolidayItem(activeItem.Id);
}
}
}
// Create new holiday item (group of item versions)
model.CopyTo(itemToSave);
itemToSave.Id = Guid.NewGuid();
if (model.HolidayId.Equals(Guid.Empty))
itemToSave.HolidayId = Guid.NewGuid();
_dbContext.Holidays.Add(itemToSave);
}
/// <summary>
/// Returns history records for Holiday
/// </summary>
/// <param name="timePoint">Current time point to mark Active, Inactive and Future records</param>
/// <returns></returns>
public HolidayListModel GetHolidayHistoryItems(Guid holidayId, DateTime timePoint)
{
bool activeItemSet = false;
DateTime validTimePoint = GetValidTimePoint(timePoint);
HolidayListModel result = new HolidayListModel();
List<Holiday> items =
(from Holiday rec in _dbContext.Holidays
orderby rec.EffectiveChangeDate descending
where rec.HolidayId.Equals(holidayId)
select rec).Take(10).ToList();
for (int index = 0; index < items.Count; index++)
{
HolidayModel currentItem = (HolidayModel)items[index];
result.Items.Add(currentItem);
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;
}
}
}
return result;
}
public void DeleteHoliday(Guid holidayId)
{
var foundItems = _dbContext.Holidays.Where(t => t.HolidayId.Equals(holidayId));
if (foundItems.Count() < 1)
throw new Exception(String.Format("Holiday (holidayId = '{0}') not found", holidayId.ToString()));
_dbContext.Holidays.RemoveRange(foundItems);
}
#endregion
}
}