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

169 lines
6.4 KiB
C#

using EnVisage.Code.BLL;
using EnVisage.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace EnVisage.Code
{
public class RateManager
{
private readonly EnVisageEntities _dbContext;
private readonly bool _isContexLocal = false;
public RateManager(EnVisageEntities dbContext)
{
if (dbContext == null)
{
_dbContext = new EnVisageEntities();
_isContexLocal = true;
}
else
{
_dbContext = dbContext;
}
}
public void Dispose()
{
if (_isContexLocal)
_dbContext.Dispose();
}
#region Public Methods
/// <summary>
/// Loads a Rate from the database.
/// </summary>
/// <param name="value">Unique identifier of the Rate .</param>
/// <param name="isReadOnly">Indicates that object will not be saved later in the code. Use <b>false</b> if you need to save an updated object.</param>
/// <returns>A <see cref="Rate"/> object retrieved from database.</returns>
public Rate Load(Guid? value, bool isReadOnly = true)
{
if (value == null || value == Guid.Empty)
return new Rate();
return isReadOnly
? _dbContext.Rates.AsNoTracking().FirstOrDefault(t => t.Id == value)
: _dbContext.Rates.Find(value);
}
public void Save(RateModel model)
{
if (model == null)
throw new ArgumentNullException("model");
#region Save Rate data
Rate dbObj = null;
if (model.Id != Guid.Empty)
dbObj = _dbContext.Rates.Find(model.Id);
if (dbObj == null)
{
dbObj = new Rate { Id = Guid.NewGuid() };
}
model.CopyTo(dbObj);
if (model.Id == Guid.Empty)
_dbContext.Rates.Add(dbObj);
else
_dbContext.Entry(dbObj).State = EntityState.Modified;
#endregion
#region Update Related Scenarios
var scenarioManager = new ScenarioManager(_dbContext);
scenarioManager.ApplyRateAndRecalculateScenarios(dbObj);
if (model.Type == RateModel.RateType.Global)
scenarioManager.RecalculateCapacityScenariosRates(dbObj);
#endregion
if (_isContexLocal)
_dbContext.SaveChanges();
}
public Dictionary<Guid, List<Rate>> GetRates(Guid expenditureCategoryId, RateModel.RateType? type)
{
return GetRates(new List<Guid>() { expenditureCategoryId }, type);
}
public Dictionary<Guid, List<Rate>> GetRates(List<Guid> expCats, RateModel.RateType? type)
{
if (expCats == null || expCats.Count <= 0)
return new Dictionary<Guid, List<Rate>>();
var ratesQuery = _dbContext.Rates.Where(x => expCats.Contains(x.ExpenditureCategoryId));
if (type.HasValue)
ratesQuery = ratesQuery.Where(x => x.Type == (short)type);
return ratesQuery.ToList().GroupBy(x => x.ExpenditureCategoryId)
.ToDictionary(x => x.Key, g => g.ToList());
}
public decimal GetRateValue(Dictionary<Guid, List<Rate>> rates, Guid expenditureCategoryId, DateTime currentDate)
{
if (expenditureCategoryId == Guid.Empty)
throw new ArgumentException("Parameter 'expenditureCatetoryId' can not be Guid.Empty");
if (rates == null || rates.Count <= 0)
return 0;
if (!rates.ContainsKey(expenditureCategoryId))
return 0;
var rate = rates[expenditureCategoryId].FirstOrDefault(x => currentDate >= x.StartDate && currentDate <= x.EndDate);
return rate != null ? rate.Rate1 : 0;
}
public Dictionary<Guid, List<Rate>> GetRates(Guid? scenarioId)
{
var localRates = _dbContext.Rates.Where(x => x.Type == (short)RateModel.RateType.Derived && x.ParentId == scenarioId).ToList();
var globalRates = _dbContext.Rates.Where(x => x.Type == (short)RateModel.RateType.Global).ToList();
return MergeRates(globalRates, localRates);
}
public Dictionary<Guid, List<Rate>> MergeRates(List<Rate> globalRates, List<Rate> localRates)
{
if (globalRates == null)
globalRates = new List<Rate>();
if (localRates == null)
localRates = new List<Rate>();
var result = new Dictionary<Guid, List<Rate>>();
var expCatsWithLocalRates = localRates.Select(x => x.ExpenditureCategoryId).ToList();
var expCatsWithGlobalRates = globalRates.Select(x => x.ExpenditureCategoryId).ToList();
foreach (var expCatId in expCatsWithLocalRates.Union(expCatsWithGlobalRates))
{
var rates = new List<Rate>();
var expCatLocal = localRates.FindAll(x => x.ExpenditureCategoryId == expCatId);
var expCatGlobal = globalRates.FindAll(x => x.ExpenditureCategoryId == expCatId);
foreach (var rateDate in expCatLocal.Select(x => x.EndDate).Union(expCatGlobal.Select(x => x.EndDate)).OrderBy(x => x))
{
var localRate = expCatLocal.FirstOrDefault(x => x.EndDate == rateDate);
var globalRate = expCatGlobal.FirstOrDefault(x => x.EndDate == rateDate);
rates.Add(localRate == null ? globalRate : localRate);
}
result.Add(expCatId, rates);
}
return result;
}
public Dictionary<Guid, List<Rate>> Get4Parents(List<Guid> parents, RateModel.RateType? type)
{
if (parents == null || parents.Count <= 0)
return new Dictionary<Guid, List<Rate>>();
var query = _dbContext.Rates.Where(x => x.ParentId.HasValue && parents.Contains(x.ParentId.Value));
if (type.HasValue)
query = query.Where(x => x.Type == (short)type.Value);
return query.ToList()
.GroupBy(x => x.ParentId.Value)
.ToDictionary(x => x.Key, g => g.ToList());
}
#endregion
}
}