923 lines
33 KiB
C#
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
|
|
|
|
}
|
|
} |