using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Threading.Tasks; using System.Web; using EnVisage.Models; namespace EnVisage.Code.BLL { public class CompanyManager : ManagerBase { public CompanyManager(EnVisageEntities dbContext) : base(dbContext) { } protected override Company InitInstance() { return new Company { Id = Guid.NewGuid() }; } protected override Company RetrieveReadOnlyById(Guid key) { return DataTable.AsNoTracking().FirstOrDefault(t => t.Id == key); } public override DbSet DataTable { get { return DbContext.Companies; } } #region Public Methods public CompanyModel GetCompanyByName(string name) { return CompanyModelBasicQuery.Where(x => x.Name == name).FirstOrDefault(); } public CompanyModel GetCompanyById(Guid id) { return CompanyModelBasicQuery.FirstOrDefault(q => q.Id == id); } /// Loads a first Company with parentId == null. /// A object. public CompanyModel LoadParent() { var parent = CompanyModelBasicQuery.FirstOrDefault(t => t.ParentCompanyId == null); if (parent == null) throw new BLLException("There is no Parent Company in the database. It should be created on application start.", false); return parent; } public CompanyModel LoadWithChildCollections(Guid companyId) { var model = LoadCompanyModel(companyId); if (model != null && model.Id != Guid.Empty) { model.ClientId = DbContext.Company2Client.AsNoTracking().Where(x => x.CompanyId == model.Id) .Select(x => x.ClientId) .ToList(); model.ViewId = DbContext.Company2View.AsNoTracking().Where(x => x.CompanyId == model.Id) .Select(x => x.ViewId) .ToList(); } return model; } public override Company Save(CompanyModel model) { var company = base.Save(model); if (Guid.Empty.Equals(model.Id)) { if (model.ClientId != null) { foreach (var clientId in model.ClientId) { var client = DbContext.Company2Client.Create(); client.Id = Guid.NewGuid(); client.ClientId = clientId; client.CompanyId = company.Id; DbContext.Company2Client.Add(client); } } if (model.ViewId != null) { foreach (var viewId in model.ViewId) { var company2View = DbContext.Company2View.Create(); company2View.Id = Guid.NewGuid(); company2View.ViewId = viewId; company2View.CompanyId = company.Id; DbContext.Company2View.Add(company2View); } } } else { var clients = DbContext.Company2Client.Where(x => x.CompanyId == model.Id).ToList(); clients.Where(x => model.ClientId == null || !model.ClientId.Contains(x.ClientId)).ToList(). ForEach(x => DbContext.Entry(x).State = EntityState.Deleted); var company2Views = DbContext.Company2View.Where(x => x.CompanyId == model.Id).ToList(); company2Views.Where(x => model.ViewId == null || !model.ViewId.Contains(x.ViewId)).ToList(). ForEach(x => DbContext.Entry(x).State = EntityState.Deleted); if (model.ClientId != null) { foreach (var clientId in model.ClientId.Where(c => !clients.Select(x => x.ClientId).Contains(c))) { var client = DbContext.Company2Client.Create(); client.Id = Guid.NewGuid(); client.ClientId = clientId; client.CompanyId = company.Id; DbContext.Company2Client.Add(client); } } if (model.ViewId != null) { foreach (var viewId in model.ViewId.Where(c => !company2Views.Select(x => x.ViewId).Contains(c))) { var company2View = DbContext.Company2View.Create(); company2View.Id = Guid.NewGuid(); company2View.ViewId = viewId; company2View.CompanyId = model.Id; DbContext.Company2View.Add(company2View); } } } #region Save of attached to company watchers and contributors // Get child companies for current, if it is parent for some var childCompaniesForCurrent = DbContext.Companies.Where(x => x.ParentCompanyId.HasValue && x.ParentCompanyId.Value.Equals(company.Id)).Select(x => x.Id).ToList(); // Remove existing records for current company and it's child companies var recsToRemove = DbContext.User2Company.Where(x => x.CompanyId.Equals(company.Id) || childCompaniesForCurrent.Contains(x.CompanyId)).ToList(); DbContext.User2Company.RemoveRange(recsToRemove); SaveCompanyUsers(company.Id, model.Contributors, CollaborationRole.Contributor); // If a user is already a contributor, we no need to save him as a watcher var watchersFiltered = (model.Contributors != null) && (model.Watchers != null) ? model.Watchers.Except(model.Contributors).ToList() : new List(); SaveCompanyUsers(company.Id, watchersFiltered, CollaborationRole.Watcher); #endregion return company; } private void SaveCompanyUsers(Guid companyId, List users, CollaborationRole role) { if ((users == null) || (users.Count < 1)) return; foreach (Guid userId in users) { User2Company newRec = new User2Company() { Id = Guid.NewGuid(), CompanyId = companyId, UserId = userId, RelationType = role }; DbContext.User2Company.Add(newRec); } } /// /// Returns All companies, available for given user, ordered by parent company. /// /// User Id /// All companies. public IList GetCompaniesByUser(Guid? userId) { IQueryable qry = null; if (userId.HasValue) { qry = from c in DbContext.Companies join u2c in DbContext.VW_User2Company on c.Id equals u2c.CompanyId where u2c.UserId.Equals(userId.Value) && ((u2c.Read == 1) || (u2c.Write == 1)) select c; } else { qry = DbContext.Companies; } var result = qry.Distinct().ToList(); return result; } /// /// Returns All companies, available for given user /// /// User Id /// Companies, available for user or all companies, if user not specified public Task> GetCompaniesByUserAsync(Guid? userId) { Task> result; if (userId.HasValue) { result = (from c in DbContext.Companies join u2c in DbContext.VW_User2Company on c.Id equals u2c.CompanyId where u2c.UserId.Equals(userId.Value) && ((u2c.Read == 1) || (u2c.Write == 1)) select c).Distinct().ToListAsync(); } else { result = DbContext.Companies.ToListAsync(); } return result; } public IList GetCompaniesByUserFiltered(List companies) { if (companies == null) throw new ArgumentNullException("companies"); var availableToUserCompanies = this.GetCompaniesByUser(null); var result = availableToUserCompanies.Where(x => companies.Contains(x.Id)).ToList(); return result; } /// /// Returns All companies, available for given user, ordered by parent company. /// /// User Id /// All companies. public IList GetCompaniesByUser4Display(Guid? userId) { IQueryable companies = null; if (userId.HasValue) { companies = (from cmp in DbContext.Companies.AsNoTracking() join visible4User in DbContext.VW_User2Company4Display on cmp.Id equals visible4User.CompanyId where (!userId.HasValue || visible4User.UserId.Equals(userId.Value)) && ((visible4User.Read == 1) || (visible4User.Write == 1)) select cmp).ToArray().Select(t=> new CompanyApiModel(t)).AsQueryable(); } else { companies = DbContext.Companies.ToArray().Select(x => new CompanyApiModel(x)).AsQueryable(); } return companies.Distinct().ToList(); } public CompanyModel LoadCompanyModel(Guid companyId) { return CompanyModelBasicQuery.FirstOrDefault(x => x.Id == companyId); } public List LoadCompanies() { return CompanyModelBasicQuery.ToList(); } public Dictionary, List> GetCompanies() { var data = CompanyModelBasicQuery.ToArray(); var result = new Dictionary, List>(); foreach (var parent in data.Where(t => !t.ParentCompanyId.HasValue).OrderBy(t => t.Name)) { var key = new KeyValuePair(parent.Id, parent.Name); if (!result.ContainsKey(key)) result.Add(key, new List()); } foreach (var child in data.Where(t => t.ParentCompanyId.HasValue).OrderBy(t => t.Name)) { var parentKey = new KeyValuePair(child.ParentCompanyId.Value, child.ParentCompanyName); // add parent if it wasnt added in previous foreach for some reason if (!result.ContainsKey(parentKey)) result.Add(parentKey, new List()); var parent = result[parentKey]; if (parent != null) parent.Add((CompanyModel)child); } return result; } #endregion #region Private Members private IQueryable CompanyModelBasicQuery { get { var query = DbContext.Companies.Include(x => x.Projects).Include(x => x.Company1) .Include(x => x.Company2).Include(x => x.Teams).AsNoTracking() .Select(x => new CompanyModel { Id = x.Id, Name = x.Name, ParentCompanyId = x.ParentCompanyId, ParentCompanyName = x.ParentCompanyId.HasValue ? x.Company2.Name : null, ProjectsCount = x.Projects.Count, CompaniesCount = x.Company1.Count, TeamsCount = x.Teams.Count }); return query; } } #endregion } }