636 lines
30 KiB
C#
636 lines
30 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;
|
|
|
|
namespace EnVisage.Code.BLL
|
|
{
|
|
/// <summary>
|
|
/// Provides ability to manage fiscal calendar.
|
|
/// </summary>
|
|
public class FiscalCalendarManager : IDisposable
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
#region Fiscal Calendar Settings
|
|
/// <summary>
|
|
/// Loads fiscal calendar setings from database.
|
|
/// </summary>
|
|
/// <returns>A <see cref="FiscalCalendarModel"/> object filled with data from SystemSettings DB table.</returns>
|
|
public FiscalCalendarModel LoadFiscalCalendarSettings(bool isReadOnly = true)
|
|
{
|
|
var model = new FiscalCalendarModel();
|
|
var dbTable = isReadOnly ? _dbContext.SystemSettings.AsNoTracking() : _dbContext.SystemSettings;
|
|
var settings = dbTable.Where(
|
|
item =>
|
|
item.Type == (int) SystemSettingType.FiscalCalendarType ||
|
|
item.Type == (int) SystemSettingType.FiscalCalendarStartDate ||
|
|
item.Type == (int) SystemSettingType.FiscalCalendarWeekEnding ||
|
|
item.Type == (int) SystemSettingType.FiscalCalendarWeekEndingType);
|
|
foreach (var systemSetting in settings)
|
|
{
|
|
switch ((SystemSettingType)systemSetting.Type)
|
|
{
|
|
case SystemSettingType.FiscalCalendarStartDate:
|
|
long ticks;
|
|
model.CurrentYearStartDate = long.TryParse(systemSetting.Value, out ticks)
|
|
? new DateTime(ticks).Date
|
|
: (DateTime?)null;
|
|
model.StartDateSettingId = systemSetting.Id;
|
|
break;
|
|
case SystemSettingType.FiscalCalendarType:
|
|
model.Type = String.IsNullOrEmpty(systemSetting.Value) ? (FiscalCalendarModel.FiscalCalendarType?)null : (FiscalCalendarModel.FiscalCalendarType)Convert.ToInt16(systemSetting.Value);
|
|
model.TypeSettingId = systemSetting.Id;
|
|
break;
|
|
case SystemSettingType.FiscalCalendarWeekEnding:
|
|
model.WeekEnding = String.IsNullOrEmpty(systemSetting.Value) ? null : (DayOfWeek?)Convert.ToInt16(systemSetting.Value);
|
|
model.WeekEndingSettingId = systemSetting.Id;
|
|
break;
|
|
case SystemSettingType.FiscalCalendarWeekEndingType:
|
|
model.WeekEndingType = String.IsNullOrEmpty(systemSetting.Value) ? (FiscalCalendarModel.CalendarYearType?)null : (FiscalCalendarModel.CalendarYearType)Convert.ToInt16(systemSetting.Value);
|
|
model.WeekEndingTypeSettingId = systemSetting.Id;
|
|
break;
|
|
}
|
|
}
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves fiscal calendar settings to the database.
|
|
/// </summary>
|
|
/// <param name="model">A model with entered fiscal calendar settings.</param>
|
|
public void SaveFiscalCalendarSettings(FiscalCalendarModel model)
|
|
{
|
|
if (model == null)
|
|
throw new ArgumentNullException("model");
|
|
|
|
#region Save Calendar Type
|
|
if (model.TypeSettingId == Guid.Empty)
|
|
{
|
|
model.TypeSettingId = Guid.NewGuid();
|
|
_dbContext.SystemSettings.Add(new SystemSetting
|
|
{
|
|
Id = model.TypeSettingId,
|
|
Type = (int)SystemSettingType.FiscalCalendarType,
|
|
Value = model.Type.HasValue ? model.Type.GetHashCode().ToString(CultureInfo.InvariantCulture) : string.Empty
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var setting = _dbContext.SystemSettings.Find(model.TypeSettingId);
|
|
if (setting == null)
|
|
{
|
|
throw new BLLException("Unable to load type of calendar setting. Please, reload the page.");
|
|
}
|
|
setting.Value = model.Type.HasValue
|
|
? model.Type.GetHashCode().ToString(CultureInfo.InvariantCulture)
|
|
: string.Empty;
|
|
_dbContext.Entry(setting).State = EntityState.Modified;
|
|
}
|
|
#endregion
|
|
|
|
#region Save Start Date
|
|
if (model.StartDateSettingId == Guid.Empty)
|
|
{
|
|
model.StartDateSettingId = Guid.NewGuid();
|
|
_dbContext.SystemSettings.Add(new SystemSetting
|
|
{
|
|
Id = model.StartDateSettingId,
|
|
Type = (int)SystemSettingType.FiscalCalendarStartDate,
|
|
Value = model.CurrentYearStartDate == null ? string.Empty : model.CurrentYearStartDate.Value.Ticks.ToString(CultureInfo.InvariantCulture)
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var setting = _dbContext.SystemSettings.Find(model.StartDateSettingId);
|
|
if (setting == null)
|
|
{
|
|
throw new BLLException("Unable to load current year start date setting. Please, reload the page.");
|
|
}
|
|
setting.Value = model.CurrentYearStartDate == null
|
|
? string.Empty
|
|
: model.CurrentYearStartDate.Value.Ticks.ToString(CultureInfo.InvariantCulture);
|
|
_dbContext.Entry(setting).State = EntityState.Modified;
|
|
}
|
|
#endregion
|
|
|
|
#region Save Week Ending Day
|
|
if (model.WeekEndingSettingId == Guid.Empty)
|
|
{
|
|
model.WeekEndingSettingId = Guid.NewGuid();
|
|
_dbContext.SystemSettings.Add(new SystemSetting
|
|
{
|
|
Id = model.WeekEndingSettingId,
|
|
Type = (int)SystemSettingType.FiscalCalendarWeekEnding,
|
|
Value = model.WeekEnding.HasValue ? model.WeekEnding.GetHashCode().ToString(CultureInfo.InvariantCulture) : string.Empty
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var setting = _dbContext.SystemSettings.Find(model.WeekEndingSettingId);
|
|
if (setting == null)
|
|
{
|
|
throw new BLLException("Unable to load week ending setting. Please, reload the page.");
|
|
}
|
|
setting.Value = model.WeekEnding.HasValue
|
|
? model.WeekEnding.GetHashCode().ToString(CultureInfo.InvariantCulture)
|
|
: string.Empty;
|
|
_dbContext.Entry(setting).State = EntityState.Modified;
|
|
}
|
|
#endregion
|
|
|
|
#region Save Week Ending Type
|
|
if (model.WeekEndingTypeSettingId == Guid.Empty)
|
|
{
|
|
model.WeekEndingTypeSettingId = Guid.NewGuid();
|
|
_dbContext.SystemSettings.Add(new SystemSetting
|
|
{
|
|
Id = model.WeekEndingTypeSettingId,
|
|
Type = (int)SystemSettingType.FiscalCalendarWeekEndingType,
|
|
Value = model.WeekEndingType.HasValue ? model.WeekEndingType.GetHashCode().ToString(CultureInfo.InvariantCulture) : string.Empty
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var setting = _dbContext.SystemSettings.Find(model.WeekEndingTypeSettingId);
|
|
if (setting == null)
|
|
{
|
|
throw new BLLException("Unable to load week ending type setting. Please, reload the page.");
|
|
}
|
|
setting.Value = model.WeekEndingType.HasValue
|
|
? model.WeekEndingType.GetHashCode().ToString(CultureInfo.InvariantCulture)
|
|
: string.Empty;
|
|
_dbContext.Entry(setting).State = EntityState.Modified;
|
|
}
|
|
#endregion
|
|
|
|
#region Update fiscal year records and scenario details records
|
|
// TODO: finish and test different use cases before uncomment this code to prevent fiscal calendar data loss
|
|
//var dictionary = new Dictionary<int, KeyValuePair<DateTime, DateTime?>>();
|
|
//var index = 0;
|
|
//foreach (var item in _dbContext.FiscalCalendars.Where(
|
|
// t => t.Type == (int?)FiscalCalendarModel.FiscalCalendarType.Week && t.NonWorking == 0).OrderBy(o => o.YearInt).ThenBy(o => o.PeriodInt)
|
|
// .Select(week => new
|
|
// {
|
|
// week.Name,
|
|
// week.Type,
|
|
// week.YearInt,
|
|
// week.QuarterInt,
|
|
// week.PeriodInt,
|
|
// week.EndDate,
|
|
// }).ToArray().Distinct())
|
|
//{
|
|
// dictionary.Add(index++, new KeyValuePair<DateTime, DateTime?>(item.EndDate.Value, null));
|
|
//}
|
|
//((System.Data.Entity.Infrastructure.IObjectContextAdapter)_dbContext).ObjectContext.ExecuteStoreCommand("TRUNCATE TABLE [FiscalCalendar]");
|
|
//UpdateFiscalCalendars(model);
|
|
//_dbContext.SaveChanges();
|
|
//index = 0;
|
|
//foreach (
|
|
// var item in
|
|
// _dbContext.FiscalCalendars.Where(
|
|
// t => t.Type == (int?)FiscalCalendarModel.FiscalCalendarType.Week && t.NonWorking == 0).OrderBy(o => o.YearInt).ThenBy(o => o.PeriodInt)
|
|
// .Select(week => new
|
|
// {
|
|
// week.Name,
|
|
// week.Type,
|
|
// week.YearInt,
|
|
// week.QuarterInt,
|
|
// week.PeriodInt,
|
|
// week.EndDate,
|
|
// }).ToArray().Distinct())
|
|
//{
|
|
// var dt = dictionary[index].Key;
|
|
// dictionary[index] = new KeyValuePair<DateTime, DateTime?>(dt, item.EndDate.Value);
|
|
// index++;
|
|
//}
|
|
|
|
//foreach (var keyValuePair in dictionary)
|
|
//{
|
|
// ((System.Data.Entity.Infrastructure.IObjectContextAdapter)_dbContext).ObjectContext.ExecuteStoreCommand
|
|
// (string.Format("UPDATE [ScenarioDetail] SET WeekEndingDate='{0}' WHERE WeekEndingDate='{1}'", keyValuePair.Value.Value, keyValuePair.Value.Key));
|
|
//}
|
|
|
|
#endregion
|
|
|
|
if (_isContexLocal)
|
|
_dbContext.SaveChanges();
|
|
}
|
|
|
|
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, prevMonth = null, prevQuarter = null, 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, prevMonth = null, prevQuarter = null, 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 Holidays
|
|
|
|
public Holiday LoadHoliday(Guid? value)
|
|
{
|
|
if (value == null || value == Guid.Empty)
|
|
return new Holiday();
|
|
|
|
var holiday = _dbContext.Holidays.Find(value);
|
|
if (holiday == null)
|
|
return new Holiday();
|
|
return holiday;
|
|
}
|
|
|
|
public void SaveHoliday(HolidayModel model)
|
|
{
|
|
if (model == null)
|
|
throw new ArgumentNullException("model");
|
|
|
|
#region Save Holiday data
|
|
Holiday holiday = null;
|
|
if (model.Id != Guid.Empty)
|
|
holiday = _dbContext.Holidays.Find(model.Id);
|
|
if (holiday == null)
|
|
{
|
|
holiday = new Holiday {Id = Guid.NewGuid()};
|
|
}
|
|
model.CopyTo(holiday);
|
|
if (model.Id == Guid.Empty)
|
|
_dbContext.Holidays.Add(holiday);
|
|
else
|
|
_dbContext.Entry(holiday).State = EntityState.Modified;
|
|
#endregion
|
|
|
|
if (_isContexLocal)
|
|
_dbContext.SaveChanges();
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_isContexLocal)
|
|
_dbContext.Dispose();
|
|
}
|
|
}
|
|
} |