private async Task CreateAlertsAsync(IEnumerable<Alert> alerts, ProjectWorkflow project,
            StateTransition<string> transition, State state, AppUser currentUser)
        {
            dynamic model = project.GetComplexModel(state.Id);

            foreach (var alert in alerts)
            {
                var matchProperties = true;
                foreach (var condition in alert.ConditionQuery.Where(c => !string.IsNullOrEmpty(c)))
                {
                    if (!project.GetComplexModelDictionary(state.Id).AsQueryable().Where(condition).Any())
                    {
                        matchProperties = false;
                        break;
                    }
                }
                if (!matchProperties)
                {
                    continue;
                }

                var projectAlert = new ProjectAlert
                {
                    CreatedBy = currentUser,
                    CreatedById = currentUser.Id,
                    ProjectId = project.Id,
                    StartDate = alert.IsRecurrent ? (DateTime?)null : DateTime.UtcNow,
                    CreatedOn = DateTime.UtcNow,
                    StateId = state.Id,
                    //IsFired = isFired,
                    IsRecurrent = alert.IsRecurrent,
                    CommitActionName = alert.CommitActionName,
                    TransitionId = int.Parse(transition.Id),
                    AlertLinkId = alert.Id
                };
                _dbContext.ProjectAlerts.Add(projectAlert);

                if (!alert.IsRecurrent)
                {
                    var message = new AlertMessage
                    {
                        From = GetEmailsByRole(alert.Action.MessageTemplate.From),
                        To = GetEmailsByRole(alert.Action.MessageTemplate.To),
                        Subject = alert.Action.MessageTemplate.Subject ?? $"{project.Company.Name} alert",
                        Body = await GetMessageHtml(alert.Action.MessageTemplate.Body, model)
                    };
                    alert.Action.DoAction(message);

                    _dbContext.ProjectAlertActions.Add(new ProjectAlertAction
                    {
                        ProjectAlert = projectAlert,
                        ProjectAlertId = projectAlert.Id,
                        From = alert.Action.MessageTemplate.From,
                        To = alert.Action.MessageTemplate.To,
                        Subject = alert.Action.MessageTemplate.Subject,
                        Body = message.Body
                    });
                }

                _historyManager.LogInfo(projectAlert.ProjectId, projectAlert.TransitionId, projectAlert, EventType.FireAlert, currentUser);
            }
            //if (alerts.Any())
            {
                _dbContext.SaveChanges();
            }
        }
		private void Execute(Func<ProjectAlertScheduled, string[]> getConditionStrings, Func<ProjectAlertScheduled, ProjectWorkflow, string, int?, bool> checkCondition)
        {
            var scheduledAlerts = GetScheduledAlerts().ToList();
            var projectsCache = new Dictionary<string, ProjectWorkflow>();
            foreach (var alert in scheduledAlerts)
            {
                var conditionStrings = getConditionStrings(alert);

                if (!conditionStrings.Any())
                {
                    continue;
                }

                ProjectWorkflow project;
                if (!projectsCache.TryGetValue(alert.Project.Id, out project))
                {
                    project = new ProjectWorkflow(alert.Project, _workflowDefinition,
                            new ProjectStoreWorkflowManager(_dbContext));
                    projectsCache.Add(alert.Project.Id, project);
                }
                
                if (project.IsDeleted || project.IsArchived)
                {
                    _dbContext.ProjectAlertsScheduled.Remove(alert);
                    continue;
                }
                //if(_dbContext.ProjectAlerts.Any(pa => pa.ProjectId == project.Id && pa.AlertLinkId == alert.AlertLinkId && pa.CreatedOn.Date == DateTime.UtcNow.Date))
                //{
                //    continue;
                //}

                var matchProperties = true;
                foreach (var condition in conditionStrings.Where(c => !string.IsNullOrEmpty(c)))
                {
                    if (!checkCondition(alert, project, condition, alert.InvoiceId))
                    {
                        matchProperties = false;
                        break;
                    }
                }
                if (!matchProperties)
                {
                    continue;
                }

                var alertLink =
                        _dbContext.AlertToProjectLinks.Include(a => a.Conditions)
                            .FirstOrDefault(a => a.Id == int.Parse(alert.AlertLinkId));

                var projectAlert = new ProjectAlert
                {
                    CreatedBy = alert?.Transition?.CreatedBy,
                    CreatedById = alert?.Transition?.CreatedBy?.Id,
                    ProjectId = project.Id,
                    StartDate = DateTime.UtcNow,
                    CreatedOn = DateTime.UtcNow,
                    StateId = alert.StateId,
                    IsRecurrent = false,
                    CommitActionName = alertLink?.CommitActionName,
                    TransitionId = alert.TransitionId,
                    AlertLinkId = alert.AlertLinkId
                };
                _dbContext.ProjectAlerts.Add(projectAlert);

                var qNum = (project.States[0].Model as QuoteOfEntry)?.QuotationNumber;
                var body = Task.Run(() => GetMessageHtml(alertLink?.Body, project.GetComplexModel(alert.StateId))).Result.Result;

                if (!((string)body).Contains(qNum))
                {
                    throw new InvalidOperationException($"qNum: {qNum}, body: {body}");
                }

                if (alertLink.SendEmail)
                {
                    var subject = Task.Run(() => GetMessageHtml((alertLink?.Subject ?? $"{project.Company.Name} alert"), project.GetComplexModel(alert.StateId))).Result.Result;
                    var message = new AlertMessage
                    {
                        From = GetEmailsByRole(alertLink?.From),
                        To = GetEmailsByRole(alertLink?.To),
                        Subject = subject,
                        Body = body
                    };

                    var mailAction = new MailAlertAction();
                    mailAction.DoAction(message);
                }

                _dbContext.ProjectAlertActions.Add(new ProjectAlertAction
                {
                    ProjectAlert = projectAlert,                    
                    From = alertLink?.From,
                    To = alertLink?.To,
                    Subject = alertLink?.Subject,
                    Body = body
                });
				
				if (!alertLink.IsRecurrent)
                {
                    _dbContext.ProjectAlertsScheduled.Remove(alert);
                }

                _historyManager.LogInfo(projectAlert.ProjectId, projectAlert.TransitionId, projectAlert, EventType.FireAlert, null);
                _dbContext.SaveChanges();
            }
        }