public async Task <string> Salvar(Aula aula, Usuario usuario, RecorrenciaAula recorrencia, int quantidadeOriginal = 0, bool ehRecorrencia = false)
        {
            if (!ehRecorrencia)
            {
                var aulaExistente = await repositorioAula.ObterAulaDataTurmaDisciplinaProfessorRf(aula.DataAula, aula.TurmaId, aula.DisciplinaId, aula.ProfessorRf);

                if (aulaExistente != null && !aulaExistente.Id.Equals(aula.Id))
                {
                    throw new NegocioException("Já existe uma aula criada neste dia para este componente curricular.");
                }

                var tipoCalendario = repositorioTipoCalendario.ObterPorId(aula.TipoCalendarioId);

                if (tipoCalendario == null)
                {
                    throw new NegocioException("O tipo de calendário não foi encontrado.");
                }

                aula.AtualizaTipoCalendario(tipoCalendario);

                await VerificaSeProfessorPodePersistirTurmaDisciplina(usuario.CodigoRf, aula.TurmaId, aula.DisciplinaId, aula.DataAula, usuario);

                var disciplinasProfessor = usuario.EhProfessorCj() ? ObterDisciplinasProfessorCJ(aula, usuario) : await ObterDisciplinasProfessor(aula, usuario);

                if (disciplinasProfessor == null || !disciplinasProfessor.Any(c => c.ToString() == aula.DisciplinaId))
                {
                    throw new NegocioException("Você não pode criar aulas para essa UE/Turma/Disciplina.");
                }

                var turma = repositorioTurma.ObterTurmaComUeEDrePorId(aula.TurmaId);

                if (turma == null)
                {
                    throw new NegocioException("Turma não localizada.");
                }

                aula.AtualizaTurma(turma);
            }

            if (aula.Id > 0)
            {
                aula.PodeSerAlterada(usuario);
            }

            var temLiberacaoExcepcionalNessaData = servicoDiaLetivo.ValidaSeEhLiberacaoExcepcional(aula.DataAula, aula.TipoCalendarioId, aula.UeId);

            if (!temLiberacaoExcepcionalNessaData && !servicoDiaLetivo.ValidarSeEhDiaLetivo(aula.DataAula, aula.TipoCalendarioId, null, aula.UeId))
            {
                throw new NegocioException("Não é possível cadastrar essa aula pois a data informada está fora do período letivo.");
            }

            if (aula.RecorrenciaAula != RecorrenciaAula.AulaUnica && aula.TipoAula == TipoAula.Reposicao)
            {
                throw new NegocioException("Uma aula do tipo Reposição não pode ser recorrente.");
            }

            var ehInclusao = aula.Id == 0;

            if (aula.RecorrenciaAula == RecorrenciaAula.AulaUnica && aula.TipoAula == TipoAula.Reposicao)
            {
                var aulas = repositorioAula.ObterAulas(aula.TipoCalendarioId, aula.TurmaId, aula.UeId, usuario.CodigoRf).Result;
                var quantidadeDeAulasSomadas = aulas.ToList().FindAll(x => x.DataAula.Date == aula.DataAula.Date).Sum(x => x.Quantidade) + aula.Quantidade;

                if (ReposicaoDeAulaPrecisaDeAprovacao(quantidadeDeAulasSomadas, aula.Turma))
                {
                    var nomeDisciplina = aula.DisciplinaNome;

                    repositorioAula.Salvar(aula);
                    PersistirWorkflowReposicaoAula(aula, aula.Turma.Ue.Dre.Nome, aula.Turma.Ue.Nome, nomeDisciplina,
                                                   aula.Turma.Nome, aula.Turma.Ue.Dre.CodigoDre);
                    return("Aula cadastrada com sucesso e enviada para aprovação.");
                }
            }
            else
            {
                if (usuario.EhProfessorCj() && aula.Quantidade > 2)
                {
                    throw new NegocioException("Quantidade de aulas por dia/disciplina excedido.");
                }

                // Busca quantidade de aulas semanais da grade de aula
                int semana = UtilData.ObterSemanaDoAno(aula.DataAula);

                var gradeAulas = await consultasGrade.ObterGradeAulasTurmaProfessor(aula.TurmaId, Convert.ToInt64(aula.DisciplinaId), semana, aula.DataAula, usuario.CodigoRf);

                var quantidadeAulasRestantes = gradeAulas == null ? int.MaxValue : gradeAulas.QuantidadeAulasRestante;

                ObterDisciplinaDaAula(aula);

                if (!ehInclusao)
                {
                    if (aula.ComponenteCurricularEol.Regencia)
                    {
                        if (aula.Turma.ModalidadeCodigo == Modalidade.EJA)
                        {
                            var aulasNoDia = await repositorioAula.ObterAulas(aula.TurmaId, aula.UeId, usuario.CodigoRf, data : aula.DataAula, aula.DisciplinaId);

                            if (aula.Quantidade != 5)
                            {
                                throw new NegocioException("Para regência de EJA só é permitido a criação de 5 aulas por dia.");
                            }
                        }
                        else if (aula.Quantidade != 1)
                        {
                            throw new NegocioException("Para regência de classe só é permitido a criação de 1 (uma) aula por dia.");
                        }
                    }
                    else
                    {
                        // Na alteração tem que considerar que uma aula possa estar mudando de dia na mesma semana, então não soma as aulas do proprio registro
                        var aulasSemana = await repositorioAula.ObterAulas(aula.TipoCalendarioId, aula.TurmaId, aula.UeId, usuario.CodigoRf, mes : null, semanaAno : semana, disciplinaId : aula.DisciplinaId);

                        var quantidadeAulasSemana = aulasSemana.Where(a => a.Id != aula.Id).Sum(a => a.Quantidade);

                        quantidadeAulasRestantes = gradeAulas == null ? int.MaxValue : gradeAulas.QuantidadeAulasGrade - quantidadeAulasSemana;
                        if ((gradeAulas != null) && (quantidadeAulasRestantes < aula.Quantidade))
                        {
                            throw new NegocioException("Quantidade de aulas superior ao limíte de aulas da grade.");
                        }
                    }
                }
                else
                {
                    if (aula.ComponenteCurricularEol.Regencia)
                    {
                        var aulasNoDia = await repositorioAula.ObterAulas(aula.TurmaId, aula.UeId, usuario.CodigoRf, data : aula.DataAula, aula.DisciplinaId);

                        if (aulasNoDia != null && aulasNoDia.Any())
                        {
                            if (aula.Turma.ModalidadeCodigo == Modalidade.EJA)
                            {
                                throw new NegocioException("Para regência de EJA só é permitido a criação de 5 aulas por dia.");
                            }
                            else
                            {
                                throw new NegocioException("Para regência de classe só é permitido a criação de 1 (uma) aula por dia.");
                            }
                        }
                    }
                    if ((gradeAulas != null) && (quantidadeAulasRestantes < aula.Quantidade))
                    {
                        throw new NegocioException("Quantidade de aulas superior ao limíte de aulas da grade.");
                    }
                }
            }

            repositorioAula.Salvar(aula);

            // Na alteração de quantidade de aulas deve 0r a frequencia se registrada
            if (!ehInclusao && quantidadeOriginal != 0 && quantidadeOriginal != aula.Quantidade)
            {
                if (consultasFrequencia.FrequenciaAulaRegistrada(aula.Id).Result)
                {
                    await servicoFrequencia.AtualizarQuantidadeFrequencia(aula.Id, quantidadeOriginal, aula.Quantidade);
                }
            }

            // Verifica recorrencia da gravação
            if (recorrencia != RecorrenciaAula.AulaUnica)
            {
                var sucessoRecorrencia = false;

                try
                {
                    Cliente.Executar <IServicoAula>(s => s.GravarRecorrencia(ehInclusao, aula, usuario, recorrencia));
                    sucessoRecorrencia = true;
                }
                catch (Exception)
                {
                    sucessoRecorrencia = false;
                }

                var mensagem = ehInclusao ? "cadastrada" : "alterada";
                return($"Aula {mensagem} com sucesso. {(sucessoRecorrencia ? $"Serão {mensagem}s aulas recorrentes, em breve você receberá uma notificação com o resultado do processamento." : "Não foi possível cadastrar as aulas recorrentes, tente novamente.")} ");
            }

            return("Aula cadastrada com sucesso.");
        }