345 lines
14 KiB
C#
345 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using EnVisage.Models;
|
|
using System.Data.Entity;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace EnVisage.Code.BLL
|
|
{
|
|
public class ViewManager : ManagerBase<View, ViewModel>
|
|
{
|
|
public ViewManager(EnVisageEntities dbContext)
|
|
: base(dbContext)
|
|
{
|
|
}
|
|
|
|
public override View Save(ViewModel model)
|
|
{
|
|
throw new NotImplementedException("Use Save(model, userId) method instead");
|
|
}
|
|
|
|
public View Save(ViewModel model, Guid userId)
|
|
{
|
|
var availableCompanies = GetVisibleToUserCompanies(userId);
|
|
var view = base.Save(model);
|
|
|
|
if (Guid.Empty.Equals(model.Id))
|
|
{
|
|
#region Create new View
|
|
|
|
if (model.Watchers != null)
|
|
{
|
|
foreach (var watcherId in model.Watchers)
|
|
{
|
|
var user2View = DbContext.User2View.Create();
|
|
user2View.Id = Guid.NewGuid();
|
|
user2View.ViewId = view.Id;
|
|
user2View.UserId = watcherId;
|
|
DbContext.User2View.Add(user2View);
|
|
}
|
|
}
|
|
|
|
if (model.Teams != null)
|
|
{
|
|
foreach (var teamId in model.Teams)
|
|
{
|
|
var team2View = DbContext.Team2View.Create();
|
|
team2View.Id = Guid.NewGuid();
|
|
team2View.ViewId = view.Id;
|
|
team2View.TeamId = teamId;
|
|
DbContext.Team2View.Add(team2View);
|
|
}
|
|
}
|
|
|
|
if (model.Companies != null)
|
|
{
|
|
// Filter companies: exclude child ones from list, if parent company selected
|
|
var companiesFiltered = this.FilterCompanyList(model.Companies.ToList(), availableCompanies);
|
|
|
|
foreach (var companyId in companiesFiltered)
|
|
{
|
|
var comp2View = DbContext.Company2View.Create();
|
|
comp2View.Id = Guid.NewGuid();
|
|
comp2View.ViewId = view.Id;
|
|
comp2View.CompanyId = companyId;
|
|
DbContext.Company2View.Add(comp2View);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
else
|
|
{
|
|
#region Update existing View
|
|
|
|
var currentWatchers = DbContext.User2View.Where(x => x.ViewId == model.Id).ToList();
|
|
var usersToRemove = currentWatchers.Where(x => model.Watchers == null || !model.Watchers.Contains(x.UserId)).ToList();
|
|
usersToRemove.ForEach(x => DbContext.Entry(x).State = EntityState.Deleted);
|
|
|
|
if (model.Watchers != null)
|
|
{
|
|
var watchersToAdd = model.Watchers.Where(c => currentWatchers.All(x => x.UserId != c)).ToList();
|
|
|
|
foreach (var watcherId in watchersToAdd)
|
|
{
|
|
var user2View = DbContext.User2View.Create();
|
|
user2View.Id = Guid.NewGuid();
|
|
user2View.ViewId = view.Id;
|
|
user2View.UserId = watcherId;
|
|
DbContext.Entry(user2View).State = EntityState.Added;
|
|
}
|
|
}
|
|
|
|
var currentTeams = DbContext.Team2View.Where(x => x.ViewId == view.Id).ToList();
|
|
var teamsToRemove = currentTeams.Where(x => model.Teams == null || !model.Teams.Contains(x.TeamId)).ToList();
|
|
teamsToRemove.ForEach(x => DbContext.Entry(x).State = EntityState.Deleted);
|
|
|
|
if (model.Teams != null)
|
|
{
|
|
var teamsToAdd = model.Teams.Where(c => !currentTeams.Select(x => x.TeamId).Contains(c)).ToList();
|
|
|
|
foreach (var teamId in teamsToAdd)
|
|
{
|
|
var team2View = DbContext.Team2View.Create();
|
|
team2View.Id = Guid.NewGuid();
|
|
team2View.ViewId = view.Id;
|
|
team2View.TeamId = teamId;
|
|
DbContext.Entry(team2View).State = EntityState.Added;
|
|
}
|
|
}
|
|
|
|
List<Guid> companiesFiltered = new List<Guid>();
|
|
if (model.Companies != null)
|
|
{
|
|
// Filter companies: exclude child ones from list, if parent company selected
|
|
companiesFiltered = this.FilterCompanyList(model.Companies.ToList(), availableCompanies);
|
|
}
|
|
|
|
var currentCompanies = DbContext.Company2View.Where(x => x.ViewId == view.Id).ToList();
|
|
var companiesToRemove = currentCompanies.Where(x => !companiesFiltered.Contains(x.CompanyId));
|
|
|
|
if ((model.Watchers == null) || (model.Watchers.Count != 1) || !model.Watchers.First().Equals(userId))
|
|
{
|
|
// If the only watcher for this view is current user, remove all deleted records.
|
|
// Otherwise, remove the only companies, current user has access to
|
|
var availableCompaniesPlain = availableCompanies.Keys.ToList();
|
|
availableCompaniesPlain.AddRange(availableCompanies.Values.SelectMany(x => x));
|
|
companiesToRemove = companiesToRemove.Where(x => availableCompaniesPlain.Contains(x.CompanyId));
|
|
}
|
|
|
|
companiesToRemove.ToList().ForEach(x => DbContext.Entry(x).State = EntityState.Deleted);
|
|
|
|
if (companiesFiltered.Count > 0)
|
|
{
|
|
var exisingCompanies = currentCompanies.Select(x => x.CompanyId).ToList();
|
|
var companiesToAdd = companiesFiltered.Where(x => !exisingCompanies.Contains(x)).ToList();
|
|
|
|
foreach (var companyId in companiesToAdd)
|
|
{
|
|
var company2View = DbContext.Company2View.Create();
|
|
company2View.Id = Guid.NewGuid();
|
|
company2View.ViewId = view.Id;
|
|
company2View.CompanyId = companyId;
|
|
DbContext.Entry(company2View).State = EntityState.Added;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
//env-753 start
|
|
if (model.Teams != null && model.Watchers != null)
|
|
{
|
|
var users = model.Watchers.Select(x => x.ToString());
|
|
var user2teams = DbContext.User2Team.Where(x => model.Teams.Contains(x.TeamId) && users.Contains(x.UserId)).ToList();
|
|
foreach (var watcherId in model.Watchers)
|
|
{
|
|
foreach (var teamId in model.Teams)
|
|
{
|
|
if (user2teams.Any(x => x.UserId.Equals(watcherId.ToString(), StringComparison.InvariantCultureIgnoreCase) && x.TeamId == teamId))
|
|
continue;
|
|
|
|
DbContext.User2Team.Add(new User2Team
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UserId = watcherId.ToString(),
|
|
TeamId = teamId
|
|
});
|
|
}
|
|
}
|
|
}
|
|
//env-753 end
|
|
|
|
return view;
|
|
}
|
|
|
|
public ViewModel LoadWithChildCollections(Guid? value, bool isReadOnly = true)
|
|
{
|
|
var result = (ViewModel)base.Load(value, isReadOnly);
|
|
if (result != null && value.HasValue)
|
|
{
|
|
var users = DbContext.User2View.Where(x => x.ViewId == value.Value).ToList();
|
|
result.Watchers = users.Select(x => x.UserId).ToList();
|
|
|
|
var teams = DbContext.Team2View.Where(t => t.ViewId == value.Value).ToList();
|
|
result.Teams = teams.Select(t => t.TeamId).ToList();
|
|
|
|
var companies = DbContext.Company2View.Where(t => t.ViewId == value.Value).ToList();
|
|
result.Companies = companies.Select(t => t.CompanyId).ToList();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
protected override View InitInstance()
|
|
{
|
|
return new View { Id = Guid.NewGuid() };
|
|
}
|
|
|
|
protected override View RetrieveReadOnlyById(Guid key)
|
|
{
|
|
return DataTable.AsNoTracking().FirstOrDefault(t => t.Id == key);
|
|
}
|
|
|
|
public override DbSet<View> DataTable
|
|
{
|
|
get
|
|
{
|
|
return DbContext.Views;
|
|
}
|
|
}
|
|
|
|
public IList<ViewListModel> GetViewsByOwner(Guid? ownerId, bool skipVirtualViews = true)
|
|
{
|
|
IList<ViewListModel> result = null;
|
|
Task<List<ViewListModel>> viewsTask = null;
|
|
Task<List<Company>> companiesTask = null;
|
|
|
|
if (ownerId.HasValue)
|
|
{
|
|
viewsTask = DbContext.User2View.Include(x => x.View).Where(x => x.UserId.Equals(ownerId.Value) && x.ViewId.HasValue)
|
|
.AsNoTracking().Select(x => new ViewListModel
|
|
{
|
|
Id = x.ViewId.Value,
|
|
Name = x.View.Name
|
|
}).ToListAsync();
|
|
}
|
|
else
|
|
{
|
|
viewsTask = Task.FromResult(new List<ViewListModel>());
|
|
}
|
|
|
|
using (viewsTask)
|
|
{
|
|
if (!skipVirtualViews)
|
|
// get all companies (parent and child) assigned to user directly (do not show virtual views for companies related to user implicitly)
|
|
// Query data in separate context to avoid query's intersection
|
|
companiesTask = (new CompanyManager(new EnVisageEntities())).GetCompaniesByUserAsync(ownerId);
|
|
else
|
|
companiesTask = Task.FromResult(new List<Company>());
|
|
|
|
using (companiesTask)
|
|
{
|
|
Task.WaitAll(viewsTask, companiesTask);
|
|
var companyVirtualViews = companiesTask.Result.Select(x => new ViewListModel
|
|
{
|
|
Id = x.Id,
|
|
Name = x.Name,
|
|
CompanyId = x.Id
|
|
});
|
|
|
|
result = viewsTask.Result.Concat(companyVirtualViews).ToList();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public List<TeamWithResourcesModel> GetTeamsWithResourcesByUser(Guid viewId, Guid userId)
|
|
{
|
|
if (Guid.Empty.Equals(viewId))
|
|
return new List<TeamWithResourcesModel>();
|
|
|
|
var views = new List<Guid>() { viewId };
|
|
var teams = GetTeamsWithResourcesByUser(views, userId);
|
|
return teams;
|
|
}
|
|
|
|
public List<TeamWithResourcesModel> GetTeamsWithResourcesByUser(List<Guid> views, Guid userId)
|
|
{
|
|
if (views == null || views.Count <= 0)
|
|
return new List<TeamWithResourcesModel>();
|
|
|
|
TeamManager teamMngr = new TeamManager(DbContext);
|
|
var viewTeams = teamMngr.GetTeamsByViewsByUser(views, userId).Select(t => t.TeamId);
|
|
|
|
var query =
|
|
(from t in DbContext.Teams
|
|
join pr in DbContext.VW_TeamResource on t.Id equals pr.TeamId into prl
|
|
from p in prl.DefaultIfEmpty()
|
|
join exp in DbContext.ExpenditureCategory on p.ExpenditureCategoryId equals exp.Id into egr
|
|
from e in egr.DefaultIfEmpty()
|
|
where viewTeams.Contains(t.Id)
|
|
orderby t.Name
|
|
select new
|
|
{
|
|
Team = t,
|
|
PeopleResource = p,
|
|
ExpCat = e
|
|
}).AsNoTracking().Distinct();
|
|
|
|
var result = new Dictionary<Guid, TeamWithResourcesModel>();
|
|
foreach (var item in query)
|
|
{
|
|
if (!result.ContainsKey(item.Team.Id))
|
|
{
|
|
result.Add(item.Team.Id, (TeamWithResourcesModel)item.Team);
|
|
}
|
|
if (item.PeopleResource != null)
|
|
result[item.Team.Id].PeopleResources.Add(PeopleResourceModel.GetPeopleResourceModel(item.PeopleResource, item.ExpCat, item.Team));
|
|
}
|
|
var teams = result.Values.ToList();
|
|
teams.ForEach(t => t.PeopleResources = t.PeopleResources.OrderBy(r => r.FirstName + r.LastName).ToList());
|
|
|
|
return teams;
|
|
}
|
|
|
|
#region Private Methods
|
|
|
|
private Dictionary<Guid, List<Guid>> GetVisibleToUserCompanies(Guid userId)
|
|
{
|
|
CompanyManager mngr = new CompanyManager(DbContext);
|
|
var visible2UserCompanies = mngr.GetCompaniesByUser(userId);
|
|
|
|
var allCompaniesTree = visible2UserCompanies.Where(x => !x.ParentCompanyId.HasValue ||
|
|
(x.ParentCompanyId.HasValue && !visible2UserCompanies.Where(z => z.Id.Equals(x.ParentCompanyId.Value)).Any()))
|
|
.ToDictionary(k => k.Id, v =>
|
|
visible2UserCompanies.Where(ch => ch.ParentCompanyId.HasValue && ch.ParentCompanyId.Value.Equals(v.Id))
|
|
.Select(ch => ch.Id).ToList());
|
|
|
|
return allCompaniesTree;
|
|
}
|
|
|
|
private List<Guid> FilterCompanyList(List<Guid> srcCompanies, Dictionary<Guid, List<Guid>> visible2UserCompaniesTree)
|
|
{
|
|
|
|
if ((srcCompanies == null) || (srcCompanies.Count < 1))
|
|
return srcCompanies;
|
|
|
|
if ((visible2UserCompaniesTree == null) || (visible2UserCompaniesTree.Count < 1))
|
|
return new List<Guid>();
|
|
|
|
var result = new List<Guid>(srcCompanies);
|
|
foreach (var prntCompany in visible2UserCompaniesTree.Keys)
|
|
{
|
|
// If parent company selected, remove all child companies from the result list
|
|
if (result.Contains(prntCompany))
|
|
result.RemoveAll(x => visible2UserCompaniesTree[prntCompany].Contains(x));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |