using EnVisage.Models; using NLog; using OptimaJet.Workflow.Core.Runtime; using Prevu.Core.Audit.Model; using Prevu.Core.Audit.Model.ResponseModels; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using OptimaJet.Workflow.Core; namespace EnVisage.Code.BLL { public class WorkFlowManager { protected readonly Logger Logger = LogManager.GetCurrentClassLogger(); public bool UseWorkFlow { get; set; } private EnVisageEntities dbContext = null; private bool isLocalContext = false; public WorkFlowManager(EnVisageEntities dbcntx) { if (dbcntx == null) { dbContext = new EnVisageEntities(); isLocalContext = true; } else { dbContext = dbcntx; isLocalContext = false; } this.UseWorkFlow = true; } #region Workflow Contacts public List GetContacts(Guid ParentId, WorkFlowContactNotificationType ntype) { var rt = new List(); var contacts = this.dbContext.WorkFlowContacts.Where(x => x.PartentId == ParentId && x.NotificationType == (int) ntype).ToList(); foreach(var c in contacts) { rt.Add(new WorkFlowContactModel() { Id = c.Id, ContactId = c.ContactId, ContactType = c.ContactType, ParentId = c.PartentId }); } return rt; } //public List GetContacts(Guid ParentId) //{ // var rt = new List(); // var contacts = this.dbContext.WorkFlowContacts.Where(x => x.PartentId == ParentId).ToList(); // foreach (var c in contacts) // { // rt.Add(new WorkFlowContactModel() // { // Id = c.Id, // ContactId = c.ContactId, // ContactType = c.ContactType, // ParentId = c.PartentId // }); // } // return rt; //} public List GetContactList(Guid ParentId, WorkFlowContactNotificationType type ) { var rt = new List(); var contacts = this.dbContext.WorkFlowContacts.Where(x => x.PartentId == ParentId && x.NotificationType ==(int) type).ToList(); foreach (var c in contacts) { rt.Add(c.ContactId); } return rt; } public List GetNotificationStates(Guid ContactParentId, WorkFlowContactNotificationType type) { var rt = new List(); var wfstates = this.dbContext.WorkFlowContacts.Where(x => x.PartentId == ContactParentId && x.NotificationType == (int) type).Select(y => y.NotificationToWorkFlowStates).ToList(); foreach(var c in wfstates) { foreach(var s in c) { if (!rt.Contains(s.State)) rt.Add(s.State); } } return rt; } public List GetContactTeamDetails(Guid parentId, WorkFlowContactNotificationType type, string state) { var rt = new List(); var contacts = GetContacts(parentId, type); var teamId = Guid.Empty; var teamName = dbContext.Teams.Where(x => x.Id == parentId).Select(x => x.Name).FirstOrDefault() ?? ""; var userIds = contacts.Select(q => q.ContactId); var users = dbContext.AspNetUsers.Where(x => userIds.Select(q => q.ToString()).Contains(x.Id)).ToDictionary(q => q.Id); var roles = dbContext.User2WorkFlowRole.Where(x => userIds.Contains(x.RoleId)).ToList(); var notificationToWorkFlowStates = dbContext.NotificationToWorkFlowStates.Where(x => userIds.Contains(x.WorkFlowContactId)).ToList(); foreach (var c in contacts) { // scenario is in wf (state==null) and there are no records for this state in the notification state table if (!string.IsNullOrEmpty(state) && !notificationToWorkFlowStates.Any(x => x.State == state && x.WorkFlowContactId == c.Id)) continue; //scenario is not in wf and we have notification state records if (string.IsNullOrEmpty(state) && notificationToWorkFlowStates.Any(x => x.WorkFlowContactId == c.Id)) continue; if (type == WorkFlowContactNotificationType.TeamScenarioAdd) { teamId = parentId; } if (c.ContactType == WorkFlowContactType.User.GetHashCode()) { var id = c.ContactId.ToString(); AspNetUser user; users.TryGetValue(id, out user); if (!string.IsNullOrEmpty(user?.Id)) { rt.Add(new WorkFlowContactDetails() { EmailAddress = user.Email, FirstName = user.FirstName, LastName = user.LastName, UserId=Guid.Parse(user.Id), TeamId=teamId, TeamName=teamName }); } } else { var wfRoles = roles.Where(x => x.RoleId == c.ContactId).ToList(); foreach(var role in wfRoles) { if (role.AspNetUser != null) { if (role.AspNetUser.User2Team.Any(x=>x.TeamId == parentId)) rt.Add(new WorkFlowContactDetails() { EmailAddress = role.AspNetUser.Email, FirstName = role.AspNetUser.FirstName, LastName = role.AspNetUser.LastName, UserId = Guid.Parse(role.AspNetUser.Id), TeamId = teamId, TeamName = teamName }); } } } } return rt; } public List GetContactProjectDetails(Guid PartentId) { var rt = new List(); var contacts = GetContacts(PartentId, WorkFlowContactNotificationType.None); foreach (var c in contacts) { if (c.ContactType == WorkFlowContactType.User.GetHashCode()) { var id = c.ContactId.ToString(); var user = this.dbContext.AspNetUsers.Where(x => x.Id == id).FirstOrDefault(); if (user != null) { if (SecurityManager.CheckProjectPermission(Guid.Parse(user.Id), PartentId, AccessLevel.Write, this.dbContext)) rt.Add(new WorkFlowContactDetails() { EmailAddress = user.Email, FirstName = user.FirstName, LastName = user.LastName, UserId = Guid.Parse(user.Id), }); } } else { var wfRoles = this.dbContext.User2WorkFlowRole.Where(x => x.RoleId == c.ContactId).ToList(); foreach (var role in wfRoles) { if (role.AspNetUser != null) { if (SecurityManager.CheckProjectPermission(Guid.Parse(role.AspNetUser.Id), PartentId,AccessLevel.Write,this.dbContext)) rt.Add(new WorkFlowContactDetails() { EmailAddress = role.AspNetUser.Email, FirstName = role.AspNetUser.FirstName, LastName = role.AspNetUser.LastName, UserId = Guid.Parse(role.AspNetUser.Id) }); } } } } return rt; } public List GetContactDetails(Guid PartentId, WorkFlowContactNotificationType ntype,Guid? ProjectId) { var rt = new List(); var contacts = GetContacts(PartentId,ntype); foreach (var c in contacts) { if (c.ContactType == WorkFlowContactType.User.GetHashCode()) { var id = c.ContactId.ToString(); var user = this.dbContext.AspNetUsers.Where(x => x.Id == id).FirstOrDefault(); if (user != null) { rt.Add(new WorkFlowContactDetails() { EmailAddress = user.Email, FirstName = user.FirstName, LastName = user.LastName, UserId = Guid.Parse(user.Id), }); } } else if (c.ContactType == WorkFlowContactType.WorkFlowGroup.GetHashCode()) { var wfRoles = this.dbContext.User2WorkFlowRole.Where(x => x.RoleId == c.ContactId).ToList(); foreach (var role in wfRoles) { if (role.AspNetUser != null) { rt.Add(new WorkFlowContactDetails() { EmailAddress = role.AspNetUser.Email, FirstName = role.AspNetUser.FirstName, LastName = role.AspNetUser.LastName, UserId = Guid.Parse(role.AspNetUser.Id) }); } } } else if (c.ContactType == WorkFlowContactType.UserGroup.GetHashCode()) { string id = c.ContactId.ToString(); var sysRoles = this.dbContext.AspNetRoles.Where(x => x.Id == id).ToList(); foreach (var role in sysRoles) { if (role.AspNetUsers != null) { foreach (var u in role.AspNetUsers) { rt.Add(new WorkFlowContactDetails() { EmailAddress = u.Email, FirstName = u.FirstName, LastName = u.LastName, UserId = Guid.Parse(u.Id) }); } } } } else if (c.ContactType == WorkFlowContactType.InternalContact.GetHashCode()) { var InternalContacts = this.dbContext.Contact2Project.Where(x => x.ShowId == ProjectId).ToList(); foreach (var ic in InternalContacts) { if (ic.Contact.Type == (int) ContactType.CompanyContact) { var user = this.dbContext.AspNetUsers.FirstOrDefault(x => x.Email == ic.Contact.Email); if (user != null) { rt.Add(new WorkFlowContactDetails() { EmailAddress = user.Email, FirstName = user.FirstName, LastName = user.LastName, UserId = Guid.Parse(user.Id) }); } } } } } return rt; } public List GetContactDetails(string RoleName, Guid ParentId, WorkFlowApprovalType type) { var rt = new List(); var users = this.dbContext.User2WorkFlowRole.Where(x => x.WorkFlowRole.RoleName == RoleName).Select(x => x.AspNetUser).ToList(); foreach (var user in users) { bool ok = false; if (type == WorkFlowApprovalType.Team) ok = this.dbContext.User2Team.Any(x => x.TeamId == ParentId && x.UserId == user.Id); else ok = SecurityManager.CheckProjectPermission(Guid.Parse(user.Id), ParentId, AccessLevel.Write, dbContext); if (ok) rt.Add(new WorkFlowContactDetails() { EmailAddress = user.Email, FirstName = user.FirstName, LastName = user.LastName, UserId = Guid.Parse(user.Id) }); } return rt; } public List GetContactDetails(string RoleName) { var rt = new List(); var wfRoles = this.dbContext.User2WorkFlowRole.Where(x => x.WorkFlowRole.RoleName == RoleName).ToList(); foreach (var role in wfRoles) { if (role.AspNetUser != null) { rt.Add(new WorkFlowContactDetails() { EmailAddress = role.AspNetUser.Email, FirstName = role.AspNetUser.FirstName, LastName = role.AspNetUser.LastName, UserId = Guid.Parse(role.AspNetUser.Id) }); } } return rt; } //public List GetContactDetails(Guid PartentId, string RoleName) //{ // var rt = new List(); // var contacts = GetContacts(PartentId); // foreach (var c in contacts) // { // if (c.ContactType == WorkFlowContactType.WorkFlowGroup.GetHashCode()) // { // var wfRoles = this.dbContext.User2WorkFlowRole.Where(x => x.RoleId == c.ContactId && x.WorkFlowRole.RoleName == RoleName).ToList(); // foreach (var role in wfRoles) // { // if (role.AspNetUser != null) // { // rt.Add(new WorkFlowContactDetails() // { // EmailAddress = role.AspNetUser.Email, // FirstName = role.AspNetUser.FirstName, // LastName = role.AspNetUser.LastName, // UserId = Guid.Parse(role.AspNetUser.Id) // }); // } // } // } // } // return rt; //} public void SaveContacts(StatusModel model) { //clear out old contacts this.DeleteContacts(model.Id); if (model.NotifyOnProjectChange) if (model.ChangeNotificationContacts.Count > 0) this.SaveContacts(model.ChangeNotificationContacts, null, model.Id, WorkFlowContactNotificationType.ProjectUpdate); if (model.NotifyOnProjectCreate) if (model.CreateNotificationContacts.Count > 0) this.SaveContacts(model.CreateNotificationContacts, null, model.Id, WorkFlowContactNotificationType.ProjectCreate); if (model.NotifyOnProjectDelete) if (model.DeleteNotificationContacts.Count > 0) this.SaveContacts(model.DeleteNotificationContacts, null, model.Id, WorkFlowContactNotificationType.ProjectDelete); } public void SaveContacts(TypeModel model) { //clear out old contacts this.DeleteContacts(model.Id); if (model.NotifyOnProjectChange) if (model.ChangeNotificationContacts.Count > 0) this.SaveContacts(model.ChangeNotificationContacts, null,model.Id, WorkFlowContactNotificationType.ProjectUpdate); if (model.NotifyOnProjectCreate) if (model.CreateNotificationContacts.Count > 0) this.SaveContacts(model.CreateNotificationContacts, null, model.Id, WorkFlowContactNotificationType.ProjectCreate); if (model.NotifyOnProjectDelete) if (model.DeleteNotificationContacts.Count > 0) this.SaveContacts(model.DeleteNotificationContacts, null, model.Id, WorkFlowContactNotificationType.ProjectDelete); } public void SaveContacts(List contacts, List states, Guid ParentId, WorkFlowContactNotificationType notifyType) { if (contacts == null) contacts = new List(); bool hasChanges=DeleteContacts(ParentId); foreach (var c in contacts) { var wfContactId = Guid.NewGuid(); var id = c.ToString(); var user = this.dbContext.AspNetUsers.Where(x => x.Id == id).FirstOrDefault(); var wfGroup = this.dbContext.WorkFlowRoles.Where(x => x.Id == c).FirstOrDefault(); var userGroup = this.dbContext.AspNetRoles.Where(x => x.Id == id).FirstOrDefault(); if (c == Utils.internalContactRoleGuid) { var wfContact = new WorkFlowContact() { ContactId = c, ContactType = WorkFlowContactType.InternalContact.GetHashCode(), PartentId = ParentId, Id = wfContactId, NotificationType = (int) notifyType }; this.dbContext.WorkFlowContacts.Add(wfContact); hasChanges = true; } else if (user != null && !string.IsNullOrEmpty(user.Id)) { var wfContact = new WorkFlowContact() { ContactId = c, ContactType = WorkFlowContactType.User.GetHashCode(), PartentId = ParentId, Id = wfContactId, NotificationType=(int) notifyType }; this.dbContext.WorkFlowContacts.Add(wfContact); hasChanges = true; } else if (wfGroup != null && wfGroup.Id != Guid.Empty) { var wfContact = new WorkFlowContact() { ContactId = c, ContactType = WorkFlowContactType.WorkFlowGroup.GetHashCode(), PartentId = ParentId, Id = wfContactId, NotificationType = (int) notifyType }; this.dbContext.WorkFlowContacts.Add(wfContact); hasChanges = true; } else if (userGroup != null && ! string.IsNullOrEmpty(userGroup.Id)) { var wfContact = new WorkFlowContact() { ContactId = c, ContactType = WorkFlowContactType.UserGroup.GetHashCode(), PartentId = ParentId, Id = wfContactId, NotificationType = (int) notifyType }; this.dbContext.WorkFlowContacts.Add(wfContact); hasChanges = true; } if (states != null && states.Count > 0) { foreach(string s in states) { var wfContactState = new NotificationToWorkFlowState() { Id = Guid.NewGuid(), State = s, WorkFlowContactId = wfContactId }; this.dbContext.NotificationToWorkFlowStates.Add(wfContactState); hasChanges = true; } } } if (this.isLocalContext && hasChanges) this.dbContext.SaveChanges(); } public void SaveContacts(List contacts,Guid ParentId) { if (contacts == null) contacts = new List(); bool hasChanges= DeleteContacts(ParentId); foreach(var c in contacts) { var wfContact = new WorkFlowContact() { ContactId = c.ContactId, ContactType = c.ContactType, PartentId = ParentId, Id = Guid.NewGuid() }; this.dbContext.WorkFlowContacts.Add(wfContact); hasChanges = true; } if (this.isLocalContext && hasChanges) this.dbContext.SaveChanges(); } public bool DeleteContacts(Guid ParentId) { bool hasChanges = false; var contacts = this.dbContext.WorkFlowContacts.Where(x => x.PartentId == ParentId).ToList(); if (contacts.Count > 0) { foreach(var c in contacts) { if (c.NotificationToWorkFlowStates != null && c.NotificationToWorkFlowStates.Count > 0) this.dbContext.NotificationToWorkFlowStates.RemoveRange(c.NotificationToWorkFlowStates.ToList()); } this.dbContext.WorkFlowContacts.RemoveRange(contacts); hasChanges = true; } if (this.isLocalContext && hasChanges) { this.dbContext.SaveChanges(); hasChanges = false; } return hasChanges; } #endregion #region WorkFlowModel public bool RecordExists(string code, Guid Id) { return this.dbContext.WorkflowSchemes.Any(x => x.Code == code && x.Id != Id); } public Guid save(WorkFlowModel m, Guid UserId) { bool isNew = false; if (m.Id == Guid.Empty) { isNew = true; m.Id = Guid.NewGuid(); } if (isNew) { var schemea = getNewSchemeRecord(); var workFlowRec = new WorkflowScheme() { Id = m.Id.Value, isActive = m.isActive, isDefault = m.isDefault, ProcessType = m.DomainId, Code = m.Code, Name = m.Name, CreatedBy = UserId, DateCreated = DateTime.Now, Scheme = schemea, isTemplate = false }; this.dbContext.WorkflowSchemes.Add(workFlowRec); } else { var wfrec = this.dbContext.WorkflowSchemes.Where(x => x.Id == m.Id).FirstOrDefault(); wfrec.isActive = m.isActive; wfrec.isDefault = m.isDefault; wfrec.ProcessType = m.DomainId; wfrec.Code = m.Code; wfrec.Name = m.Name; wfrec.UpdatedBy = UserId; wfrec.UpdateDate = DateTime.Now; this.dbContext.Entry(wfrec).State = System.Data.Entity.EntityState.Modified; } if (m.isDefault) reSetDefaults(m.DomainId, m.Id.Value); if (this.isLocalContext) this.dbContext.SaveChanges(); return m.Id.Value; } private string getNewSchemeRecord() { var Scheme = this.dbContext.WorkflowSchemes.Where(x => x.isTemplate == true).Select(x => x.Scheme).FirstOrDefault(); return Scheme; } private void reSetDefaults(int ProcessType, Guid Id) { var defaults=this.dbContext.WorkflowSchemes.Where(x => x.ProcessType == ProcessType && x.isDefault && x.Id != Id).ToList(); foreach(var d in defaults) { d.isDefault = false; this.dbContext.Entry(d).State = System.Data.Entity.EntityState.Modified; } } public void Delete(WorkFlowModel model) { var schemea=this.dbContext.WorkflowProcessSchemes.Where(x => x.Id == model.SchemeId).FirstOrDefault(); if (schemea != null) this.dbContext.WorkflowProcessSchemes.Remove(schemea); var wfheader = this.dbContext.WorkflowSchemes.Where(x => x.Id == model.Id).FirstOrDefault(); if (wfheader != null) { var t2w = this.dbContext.Type2WorkFlowScheme.Where(x => x.WorkFlowSchemeId == wfheader.Id).ToList(); if (t2w != null && t2w.Count > 0) this.dbContext.Type2WorkFlowScheme.RemoveRange(t2w); this.dbContext.WorkflowSchemes.Remove(wfheader); } if (this.isLocalContext) this.dbContext.SaveChanges(); } public WorkFlowModel Load(Guid? Id) { var wf = dbContext.WorkflowSchemes.Where(x => x.Id == Id.Value).FirstOrDefault(); if (wf != null && wf.Id != Guid.Empty) { var rt = new WorkFlowModel() { Id = wf.Id, DomainId = wf.ProcessType, isDefault = wf.isDefault, ItemsInWorkFlow = GetInstanaceCount(wf.Code), Name = wf.Code, isActive = wf.isActive }; rt.WorkFlowRoles = this.getRolesByName(); return rt; } else { var rt = new WorkFlowModel(); rt.WorkFlowRoles = this.getRolesByName(); return rt; } } public int GetInstanaceCount(string schemeCode) { var schemeId = this.dbContext.WorkflowProcessSchemes.Where(x => x.SchemeCode == schemeCode).Select(x => x.Id).FirstOrDefault(); if (schemeId != null && schemeId != Guid.Empty) return this.dbContext.WorkflowProcessInstances.Where(x => x.SchemeId == schemeId).Distinct().Count(); return 0; } public WorkFlowModel LoadNewScheme() { return new WorkFlowModel() { Id = Guid.Empty, Name = "new" }; } public IQueryable WorkFlowModelBasicQuery { get { var roles = this.getRolesByName(); return from c in dbContext.VW_WorkflowModelView.AsNoTracking().Where(x => x.isTemplate == false) select new WorkFlowModel() { Id = c.Id, DomainId = c.ProcessType, isDefault = c.isDefault, ItemsInWorkFlow =(c.totalRecordInWorkFlow.HasValue?c.totalRecordInWorkFlow.Value:0), Name = c.Name, isActive = c.isActive, WorkFlowRoles= roles }; } } #endregion #region WorkflowEngineCommands public void DoWorkFlowAction(List actions, Guid ScenarioId, Guid userid,string schemeCode, List updatedTeams) { if (updatedTeams == null) updatedTeams = new List(); if (!isProcessExists(ScenarioId)) CreateDocinstance(userid, ScenarioId, schemeCode); if (actions != null) { foreach (var wfActions in actions) { if (wfActions.Selected) { (new NotificationManager(this.dbContext)).RemoveNotification(userid, ScenarioId); bool cmdExed = ExecuteCommand(ScenarioId, wfActions.command, userid.ToString(), "TeamUpdates", updatedTeams); } } } } public void SetWorkFlowState(List states, Guid ScenarioId, Guid userid, string schemeCode) { if (!isProcessExists(ScenarioId)) CreateDocinstance(userid, ScenarioId, schemeCode); if (states != null) { foreach (var state in states) { if (state.Selected) { this.SetState(userid, ScenarioId, null, state); } } } } public string getScenarioSchemeName(Guid ScenarioID) { var schemeId = this.dbContext.WorkflowProcessInstances.Where(x => x.Id == ScenarioID).Select(y => y.SchemeId).FirstOrDefault(); if (!schemeId.HasValue) return null; return this.dbContext.WorkflowProcessSchemes.Where(x => x.Id == schemeId.Value).Select(x => x.SchemeCode).FirstOrDefault(); //if (!string.IsNullOrEmpty(code)) // return this.dbContext.WorkflowSchemes.Where(x => x.Code == code).Select(x => x.Name).FirstOrDefault(); return null; } public void RemoveFormWorkFlow(Guid DocumentId) { if (!this.isProcessExists(DocumentId)) return; WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).DeleteInstance(DocumentId); var approvals = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == DocumentId).ToList(); this.dbContext.WorkFlowParallelApprovals.RemoveRange(approvals); var documentstring = DocumentId.ToString(); var projectId = this.dbContext.Scenarios.Where(x => x.Id == DocumentId).Select(x => x.ParentId).FirstOrDefault(); if (!projectId.HasValue) projectId = Guid.Empty; var projectIdStr = projectId.Value.ToString(); var notifications = this.dbContext.Notifications.Where(x => (x.IdinLink == DocumentId || x.Link.Contains(documentstring) || x.IdinLink == projectId.Value || x.Link.Contains(projectIdStr)) && x.WorkFlowState != null); this.dbContext.Notifications.RemoveRange(notifications); if (this.isLocalContext) this.dbContext.SaveChanges(); } public WorkFlowState GetCurrentState(Guid DocumentId) { if (DocumentId == Guid.Empty) return null; if (!this.isProcessExists(DocumentId)) return null; var so = WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).GetCurrentState(DocumentId); if (so != null) return new WorkFlowState() { Id = Guid.NewGuid(), HasChanges = false, Selected = false, state = so.Name }; else return null; } public List GetProjectStates(Guid DocumentId) { var rt =new List(); if (DocumentId == Guid.Empty) return rt; var ScenarioIds =this.dbContext.Scenarios.Where(x => x.ParentId == DocumentId && x.Type == (int) ScenarioType.Portfolio).Select(y => y.Id).ToList(); foreach (var ScenarioId in ScenarioIds) { if (!this.isProcessExists(ScenarioId)) continue; var so = WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).GetCurrentState(ScenarioId); if (so != null) rt.Add(new WorkFlowState() { Id = Guid.NewGuid(), HasChanges = false, Selected = false, state = so.Name }); } return rt; } public bool isProcessExists(Guid processId) { return WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).IsProcessExists(processId); } public void CreateDocinstance(Guid userId, Guid DocumentId, string schemeCode) { WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).CreateInstance(schemeCode, DocumentId, userId.ToString(), null); } public void SetState(Guid UserId, Guid Documentid, Dictionary parms, WorkFlowState stateModel) { if (parms == null) parms = new Dictionary(); WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).SetState(Documentid, UserId.ToString(), UserId.ToString(), stateModel.state, parms); } public IEnumerable GetStates(string SchemeaCode) { return WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).GetAvailableStateToSet(SchemeaCode, null); } public bool ExecuteCommand( Guid DocumentId, string cmdName, Guid UserId) { return ExecuteCommand(DocumentId, cmdName, UserId.ToString(), null, string.Empty ); } public bool ExecuteCommand(Guid DocumentId, string cmdName, string UserId, string ParmName, List ParmValue) { try { var commands = WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).GetAvailableCommands(DocumentId, UserId); var command = commands.FirstOrDefault( c => c.CommandName.Equals(cmdName, StringComparison.CurrentCultureIgnoreCase)); if (command == null) return false; if (command.Parameters.Count(p => p.ParameterName == ParmName) == 1) command.Parameters.Single(p => p.ParameterName == ParmName).Value = ParmValue ?? new List(); WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).ExecuteCommand(command, UserId, UserId); return true; } catch (Exception dd) { var sb = DateTime.Now.ToString() + ": " + dd.Message; var logger = LogManager.GetCurrentClassLogger(); if (logger != null) logger.Fatal(sb.ToString()); } return false; } public bool ExecuteCommand( Guid DocumentId, string cmdName, string UserId, string ParmName, string ParmValue) { try { var commands = WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).GetAvailableCommands(DocumentId, UserId); var command = commands.FirstOrDefault( c => c.CommandName.Equals(cmdName, StringComparison.CurrentCultureIgnoreCase)); if (command == null) return false; if (command.Parameters.Count(p => p.ParameterName == ParmName) == 1) command.Parameters.Single(p => p.ParameterName == ParmName).Value = ParmValue ?? string.Empty; WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).ExecuteCommand(command, UserId, UserId); return true; } catch (Exception dd) { var sb = DateTime.Now.ToString() + ": " + dd.Message; var logger = LogManager.GetCurrentClassLogger(); if (logger != null) logger.Fatal(sb.ToString()); } return false; } public List GetWorkFlowStates(string schemeaName) { var schemeaId = this.dbContext.WorkflowSchemes.Where(x => x.Name == schemeaName).Select(x => x.Id).FirstOrDefault(); return GetWorkFlowStates(schemeaId); } public List GetWorkFlowStates(Guid schemeaId) { var rt = new List(); var schemeaCode = this.dbContext.WorkflowSchemes.Where(x => x.Id == schemeaId).Select(x => x.Code).FirstOrDefault(); if (string.IsNullOrEmpty(schemeaCode)) return rt; var states = GetStates(schemeaCode); foreach(var state in states) { rt.Add(new WorkFlowState() { Id = Guid.NewGuid(), HasChanges = false, Selected = false, state = state.Name }); } return rt; } public List getStatesForProcess(string SchemeName) { var rt = new List(); var schemas = this.dbContext.WorkflowSchemes.Where(x => x.isActive != false && (x.Name == SchemeName || x.Code == SchemeName)).Select(x => x.Id).ToList(); foreach (var s in schemas) { var states = this.GetWorkFlowStates(s); foreach (var state in states) { if (!rt.Any(x => x.state == state.state)) rt.Add(state); } } return rt; } public List getAllStates() { var rt = new List(); var schemas = this.dbContext.WorkflowSchemes.Where(x => x.isActive != false && x.isTemplate == false).Select(x => x.Id).ToList(); foreach(var s in schemas) { var states = this.GetWorkFlowStates(s); foreach(var state in states) { if (!rt.Any(x => x.state == state.state)) rt.Add(state); } } return rt; } public List GetWorkFlowCommands(Guid DocumentId, Guid userId, bool ignoreNoOption =false) { List rt = new List(); try { bool canSave = false; var cmds = GetAvailableCommands(userId, DocumentId, ignoreNoOption); foreach (var cmd in cmds) { canSave = (cmd.CommandName.ToLower().Equals("approved")) || (cmd.CommandName.ToLower().Equals("rejected")) || (cmd.CommandName.ToLower().Equals("counter")); var cmdObj = new WorkFlowCommand() { command = cmd.CommandName, Selected = false, Id = DocumentId, HasChanges = canSave }; rt.Add(cmdObj); } } catch (Exception dd) { var sb = DateTime.Now.ToString() + ": " + dd.Message; var logger = LogManager.GetCurrentClassLogger(); if (logger != null) logger.Fatal(sb.ToString()); } return rt; } public List GetAvailableCommands(Guid UserId, Guid documentid, bool ignoreNoOption=false) { if (!isProcessExists(documentid)) return new List(); List rt = new List(); var cmds = WorkFlowEngine.Runtime(dbContext.Database.Connection.ConnectionString).GetAvailableCommands(documentid, UserId.ToString()); //see if the user has already completed approval for this wf item at this step //if so they have no other commands to exec var exec_cmds=this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == documentid && x.UserId == UserId && x.IsActive == true && x.Approved == true).ToList(); if (!ignoreNoOption) rt.Add(new WorkFlowCommandModel() { CommandName = "No Change" }); foreach (var c in cmds) { if (exec_cmds.Any(x => x.StepName == c.CommandName)) return new List(); rt.Add(new WorkFlowCommandModel() { Classifier = c.Classifier.GetHashCode(), CommandName = c.CommandName, Identities = c.Identities.ToList(), IsForSubprocess = c.IsForSubprocess, LocalizedName = c.LocalizedName, Parameters = ConvertParms(c.Parameters), ProcessId = c.ProcessId, ValidForActivityName = c.ValidForActivityName, ValidForStateName = c.ValidForStateName }); } return rt; } private List ConvertParms(IEnumerable parms) { List rt = new List(); foreach (var p in parms) { rt.Add(new WorkFlowParameter() { DefaultValue = p.DefaultValue, isRequired = p.IsRequired, LocalizedName = p.LocalizedName, ParameterName = p.ParameterName, Type = p.Type, TypeName = p.TypeName, Value = p.Value }); } return rt; } #endregion #region rolesModel public IQueryable WorkFlowRoleModelBasicQuery { get { return from c in dbContext.VW_WorkflowRoleModelView.AsNoTracking() select new WorkFlowRoleModel() { Id = c.Id, RoleName = c.RoleName, UserCount = (c.UsersInRole.HasValue ? c.UsersInRole.Value : 0), }; } } public bool UserInAnyRole(string email, List roleNames) { if (roleNames.Count == 0) return true; var roles = this.dbContext.User2WorkFlowRole.Where(x => x.AspNetUser.Email == email).Select(x => x.WorkFlowRole).ToList(); foreach(var r in roleNames) if (roles.Any(x => x.RoleName == r)) return true; return false; } public List getRolesByName() { return this.dbContext.WorkFlowRoles.Select(x => x.RoleName).ToList(); } public List getAllRolesByName() { var wfRoles = getRolesByName(); var aspRoles = this.dbContext.AspNetRoles.Select(x => x.Name).ToList(); wfRoles.AddRange(aspRoles); // var aspnetUsers = this.dbContext.AspNetUsers.Where(x => x.Type == (int) UserType.Active).Select(x => x.FirstName + " " + x.LastName); return wfRoles; } public bool RoleRecordExists(string RoleName, Guid Id) { bool exists= this.dbContext.WorkFlowRoles.Any(x => x.RoleName == RoleName && x.Id != Id); if (exists) return exists; exists = this.dbContext.AspNetRoles.Any(x => x.Name == RoleName); return exists; } public void DeleteRole(WorkFlowRoleModel model) { var u2rs = this.dbContext.User2WorkFlowRole.Where(x => x.RoleId == model.Id).ToList(); if (u2rs != null && u2rs.Count > 0) this.dbContext.User2WorkFlowRole.RemoveRange(u2rs); var wfrm=this.dbContext.WorkFlowRoles.Where(x => x.Id == model.Id).FirstOrDefault(); if (wfrm != null) this.dbContext.WorkFlowRoles.Remove(wfrm); if (this.isLocalContext) this.dbContext.SaveChanges(); } public WorkFlowRoleModel LoadRole(Guid? Id) { var wf = dbContext.WorkFlowRoles.Where(x => x.Id == Id.Value).FirstOrDefault(); if (wf != null && wf.Id != Guid.Empty) return new WorkFlowRoleModel() { Id = wf.Id, RoleName=wf.RoleName, UserCount=wf.User2WorkFlowRole.Count }; else return new WorkFlowRoleModel(); } public Guid saveRole(WorkFlowRoleModel m) { bool isNew = false; if (m.Id == Guid.Empty) { isNew = true; m.Id = Guid.NewGuid(); } if (isNew) { var workFlowRoleRec = new WorkFlowRole() { Id = m.Id.Value, RoleName=m.RoleName }; this.dbContext.WorkFlowRoles.Add(workFlowRoleRec); } else { var wfrec = this.dbContext.WorkFlowRoles.Where(x => x.Id == m.Id).FirstOrDefault(); wfrec.RoleName = m.RoleName; this.dbContext.Entry(wfrec).State = System.Data.Entity.EntityState.Modified; } if (this.isLocalContext) this.dbContext.SaveChanges(); return m.Id.Value; } public Dictionary GetProjectApproversForRole(Guid ProjectId, string step,Guid WorkFlowProcessId,string workflowRole) { var rt = new Dictionary(); var usersInRole=this.dbContext.vw_User2WorkFlowRoles.Where(x => x.RoleName == workflowRole).ToList(); var approvedAlready = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == WorkFlowProcessId && x.StepName== step && x.IsActive).ToList(); foreach(var user in usersInRole) { var userID = Guid.Parse(user.Id); if (!SecurityManager.CheckProjectPermission(userID, ProjectId, AccessLevel.Write, dbContext)) continue; var alreadApproved= approvedAlready.Where(x => x.UserId == userID).Select(y => y.Approved).FirstOrDefault(); if (!rt.ContainsKey(userID)) { if (alreadApproved != null) rt.Add(userID, alreadApproved.Value); else { rt.Add(userID, false); this.dbContext.WorkFlowParallelApprovals.Add(new WorkFlowParallelApproval() { Id = Guid.NewGuid(), Approved = false, IsActive = true, ProcessId = WorkFlowProcessId, StepName = step, GroupId = null, UserId = userID }); } } } var approvelRecsToRemove = approvedAlready.Where(x => !rt.Keys.Contains(x.UserId)).ToList(); foreach(var a in approvelRecsToRemove) { this.dbContext.WorkFlowParallelApprovals.Remove(a); this.dbContext.Entry(a).State = System.Data.Entity.EntityState.Deleted; } if (this.isLocalContext) this.dbContext.SaveChanges(); return rt; } public Dictionary GetTeamApproversForRole(Guid teamId, string step, Guid WorkFlowProcessId, string workflowRole) { var rt = new Dictionary(); var usersInRole = this.dbContext.vw_User2Team2WorkflowRoleContactInfo.Where(x => x.RoleName == workflowRole && x.TeamId == teamId).ToList(); var approvedAlready = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == WorkFlowProcessId && x.StepName == step && x.IsActive && x.GroupId == teamId).ToList(); foreach (var user in usersInRole) { var userID = Guid.Parse(user.Id); var alreadApproved = approvedAlready.Where(x => x.UserId == userID).Select(y => y.Approved).FirstOrDefault(); if (!rt.ContainsKey(userID)) { if (alreadApproved != null) rt.Add(userID, alreadApproved.Value); else { rt.Add(userID, false); this.dbContext.WorkFlowParallelApprovals.Add(new WorkFlowParallelApproval() { Id = Guid.NewGuid(), Approved = false, IsActive = true, ProcessId = WorkFlowProcessId, StepName = step, GroupId = teamId, UserId = userID }); } } } var approvelRecsToRemove = approvedAlready.Where(x => !rt.Keys.Contains(x.UserId) && x.GroupId == teamId).ToList(); foreach (var a in approvelRecsToRemove) { this.dbContext.WorkFlowParallelApprovals.Remove(a); this.dbContext.Entry(a).State = System.Data.Entity.EntityState.Deleted; } if (this.isLocalContext) this.dbContext.SaveChanges(); return rt; } public Dictionary GetCostCenterApproversForRole(Guid teamId, string step, Guid WorkFlowProcessId, string workflowRole,Guid CostCenter) { var rt = new Dictionary(); var usersInRole = this.dbContext.vw_User2Team2WorkflowRoleContactInfo.Where(x => x.RoleName == workflowRole && x.TeamId == teamId).ToList(); var approvedAlready = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == WorkFlowProcessId && x.StepName == step && x.IsActive).ToList(); foreach (var user in usersInRole) { var userID = Guid.Parse(user.Id); var alreadApproved = approvedAlready.Where(x => x.UserId == userID).Select(y => y.Approved).FirstOrDefault(); if (!rt.ContainsKey(userID)) { if (alreadApproved != null) rt.Add(userID, alreadApproved.Value); else { rt.Add(userID, false); this.dbContext.WorkFlowParallelApprovals.Add(new WorkFlowParallelApproval() { Id = Guid.NewGuid(), Approved = false, IsActive = true, ProcessId = WorkFlowProcessId, StepName = step, GroupId = CostCenter, UserId = userID }); } } } //var approvelRecsToRemove = approvedAlready.Where(x => !rt.Keys.Contains(x.UserId) && x.GroupId == CostCenter).ToList(); //foreach (var a in approvelRecsToRemove) //{ // this.dbContext.WorkFlowParallelApprovals.Remove(a); // this.dbContext.Entry(a).State = System.Data.Entity.EntityState.Deleted; //} if (this.isLocalContext) this.dbContext.SaveChanges(); return rt; } public void SetApprovalValue(Guid UserId, bool approved, Guid ProcessId, string step, WorkFlowApprovalType approvalType, Guid ProjectId) { var creditIds = this.dbContext.ScenarioDetail.Where(x => x.ParentID == ProcessId).Select(x => x.ExpenditureCategory.CreditId).Distinct().ToList(); var ECLists = dbContext.ScenarioDetail.Where(x => x.ParentID == ProcessId).Select(x => x.ExpenditureCategoryId).Distinct().ToList(); if (approvalType == WorkFlowApprovalType.AllTeam || approvalType == WorkFlowApprovalType.Team || approvalType == WorkFlowApprovalType.COSTCENTER || approvalType == WorkFlowApprovalType.TeamToEC) { var groupId = Guid.Empty; var teamsInProject = new List(); if (approvalType == WorkFlowApprovalType.Team) teamsInProject = this.dbContext.Team2Project.Where(x => x.ProjectId == ProjectId).Select(x => x.Team.Id).ToList(); else if (approvalType == WorkFlowApprovalType.AllTeam) teamsInProject = this.dbContext.Teams.Select(x => x.Id).ToList(); else if (approvalType == WorkFlowApprovalType.COSTCENTER) teamsInProject = dbContext.Teams.Where(x => creditIds.Contains((x.CostCenterId.HasValue ? x.CostCenterId.Value : Guid.Empty))).Select(x => x.Id).ToList(); else if (approvalType == WorkFlowApprovalType.TeamToEC) teamsInProject = dbContext.VW_TeamResource.Where(x => ECLists.Contains(x.ExpenditureCategoryId)).Select(x => x.TeamId).Distinct().ToList(); string userid = UserId.ToString(); var user2Teams = this.dbContext.vw_User2Team2WorkflowRoleContactInfo.Where(x => x.Id == userid && teamsInProject.Contains(x.TeamId)).ToList(); foreach (var user2Team in user2Teams) { if (approvalType == WorkFlowApprovalType.Team || approvalType == WorkFlowApprovalType.AllTeam || approvalType == WorkFlowApprovalType.TeamToEC) groupId = user2Team.TeamId; else if (approvalType == WorkFlowApprovalType.COSTCENTER) { var tmpG = this.dbContext.Teams.Where(x => x.Id == user2Team.TeamId).Select(x => x.CostCenterId).FirstOrDefault(); if (tmpG.HasValue && tmpG.Value != Guid.Empty) groupId = tmpG.Value; else groupId = Guid.Empty; } var approvelRec = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == ProcessId && x.UserId == UserId && x.StepName == step && x.GroupId == groupId && x.IsActive).FirstOrDefault(); if (approvelRec == null) { approvelRec = new WorkFlowParallelApproval() { Id = Guid.NewGuid(), UserId = UserId, ProcessId = ProcessId, Approved = approved, StepName = step, GroupId = groupId, DateApproved = DateTime.Now, IsActive = true }; this.dbContext.WorkFlowParallelApprovals.Add(approvelRec); this.dbContext.Entry(approvelRec).State = System.Data.Entity.EntityState.Added; } else { approvelRec.Approved = approved; approvelRec.IsActive = true; approvelRec.DateApproved = DateTime.Now; this.dbContext.Entry(approvelRec).State = System.Data.Entity.EntityState.Modified; } ClearApprovelNotificiation(ProcessId, groupId, UserId); } } else if (approvalType == WorkFlowApprovalType.Project) { var approvelRec = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == ProcessId && x.UserId == UserId && x.StepName == step && x.IsActive).FirstOrDefault(); if (approvelRec == null) { approvelRec = new WorkFlowParallelApproval() { Id = Guid.NewGuid(), UserId = UserId, ProcessId = ProcessId, Approved = approved, StepName = step, GroupId = null, DateApproved = DateTime.Now, IsActive = true }; this.dbContext.WorkFlowParallelApprovals.Add(approvelRec); this.dbContext.Entry(approvelRec).State = System.Data.Entity.EntityState.Added; } else { approvelRec.Approved = approved; approvelRec.IsActive = true; approvelRec.DateApproved = DateTime.Now; this.dbContext.Entry(approvelRec).State = System.Data.Entity.EntityState.Modified; } } else if (approvalType == WorkFlowApprovalType.ADHOC) { var approvelRec = this.dbContext.WorkFlowParallelApprovals.Where(x => x.ProcessId == ProcessId && x.UserId == UserId && x.StepName == step && x.IsActive).FirstOrDefault(); if (approvelRec == null) { approvelRec = new WorkFlowParallelApproval() { Id = Guid.NewGuid(), UserId = UserId, ProcessId = ProcessId, Approved = approved, StepName = step, GroupId = null, DateApproved = DateTime.Now, IsActive = true }; this.dbContext.WorkFlowParallelApprovals.Add(approvelRec); this.dbContext.Entry(approvelRec).State = System.Data.Entity.EntityState.Added; } else { approvelRec.Approved = approved; approvelRec.IsActive = true; approvelRec.DateApproved = DateTime.Now; this.dbContext.Entry(approvelRec).State = System.Data.Entity.EntityState.Modified; } } if (this.isLocalContext) this.dbContext.SaveChanges(); } private void ClearApprovelNotificiation(Guid ProcessId, Guid groupId, Guid UserId) { string ProcessIdstr = ProcessId.ToString(); var notifications = this.dbContext.Notifications.Where(x => x.IdinLink == ProcessId || x.Link.Contains(ProcessIdstr)).ToList(); foreach (var n in notifications) { if (n.WorkFlowState == null) continue; if (!this.dbContext.WorkFlowParallelApprovals.Any(x => x.GroupId == groupId && x.ProcessId == ProcessId && x.UserId == n.ParentId)) continue; if (n.ParentId != UserId) { this.dbContext.Notifications.Remove(n); this.dbContext.Entry(n).State = System.Data.Entity.EntityState.Deleted; } } } #endregion } }