/// <summary>
        /// Gravação polimórfica -> além de gravar o Parecer, replica os dados da solicitacao nas tabelas de Parecer
        /// </summary>
        /// <param name="parecer"></param>
        public override void Salvar(ParecerSolicitacao parecer)
        {
            try
            {
                base.Salvar(parecer);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// Utiliza dados da solicitacao ou de pareceres anteriores para preencher o parecer que sera salvo.
        /// Revisado
        /// </summary>
        /// <param name="p"></param>
        /// <param name="s"></param>
        /// <param name="parAnterior">OPCIONAL: o parecer usado como base.</param>
        public void PreencheParecerComDadosSolicitacao(ParecerSolicitacao p, Solicitacao s)
        {
            if (s != null)
            {

                p.DadosPrincipaisAprovacao.Add((DadoPrincipalAprovacao)s.DadosPrincipaisSolicitacao.Last());
                foreach (var c in s.Caracteristicas)
                {
                    p.CaracteristicasAprovacao.Add((CaracteristicaClienteAprovacao)c);
                }

                p.DefinicoesAprovacao.Add((DefinicoesClienteAprovacao)s.Definicoes.Last());

                foreach (var e in s.EnderecosCobranca)
                {
                    p.EnderecosCobrancaAprovacao.Add((EnderecoCobrancaClienteAprovacao)e);
                }

                foreach (var e in s.EnderecosEntrega)
                {
                    p.EnderecosEntregaAprovacao.Add((EnderecoEntregaClienteAprovacao)e);
                }

                foreach (var r in s.Referencias)
                {
                    p.ReferenciasAprovacao.Add((ReferenciaClienteAprovacao)r);
                }

                foreach (var c in s.Contatos)
                {
                    p.ContatosAprovacao.Add((ContatoClienteAprovacao)c);
                }

                foreach (var doc in s.DocumentosAnexados)
                {
                    p.DocumentosAnexadosAprovacao.Add((DocumentoAnexadoAprovacao)doc);
                }

                foreach (var soc in s.Socios)
                {
                    p.SociosAprovacao.Add((SocioEmpresaAprovacao)soc);
                }
            }
        }
        public ActionResult EnviarParaAprovacao(string textoParecer)
        {
            using (var historicoBLL = new HistoricoSolicitacaoBLL())
            {
                var parecerSolicitacaoBLL = new ParecerSolicitacaoBLL();
                var configBLL = new ConfiguracaoWorkflowBLL();

                var s = Session["Solicitacao"] as Solicitacao;

                try
                {
                    s.TxtJustificativa = textoParecer;

                    #region Faz a configuração para o workflow

                    var config = new ConfiguracaoWorkflow();

                    //s.CodTipoSolicitacao =

                    config.StrUsuAlcada = String.IsNullOrEmpty(s.Definicoes.Last().VlrLimite) ? "0" : s.Definicoes.Last().VlrLimite.ToString(); //obter o valor do limite.
                    config.StrUsuAlcadamax = String.IsNullOrEmpty(s.Definicoes.Last().VlrLimite) ? "0" : s.Definicoes.Last().VlrLimite.ToString();
                    config.StrUsuTipsol = Convert.ToInt32(TipoSolicitacao.Inclusao).ToString();
                    config.UsuTipsol = Convert.ToInt32(TipoSolicitacao.Inclusao); // SEMPRE INCLUSÃO para o workflow.

                    config.UsuAlcada = Convert.ToDouble(config.StrUsuAlcada);
                    config.UsuAlcadamax = Convert.ToDouble(config.StrUsuAlcadamax);
                    config = configBLL.ObterConfiguracao(config, true);

                    s.nivelMaximo = configBLL.ObterNivel(config);
                    //config.UsuNivel = configBLL.ObterNivel(config);
                    #endregion

                    #region Salvar o parecer, um novo registro no histórico, e os dados do parecer.

                    // gravar o Primeiro parecer (primeiro parecer de solicitação, e o 'aprovador' será definido pela configuração.)
                    var p = new ParecerSolicitacao();

                    var historico = new HistoricoSolicitacao();

                    // Mudar da situação 'DIGITANDO - 1' para 'AGUARDANDO APROVAÇÃO - 2'
                    historico.CodSituacaoSolicitacao = Convert.ToInt32(SituacaoSolicitacao.AguardandoAprovacao);
                    historico.DatEncaminhamento = DateTime.Now;
                    historico.Solicitacao = s;
                    s.CodSituacaoAtual = Convert.ToInt32(SituacaoParecer.AguardandoAprovacao);

                    //pegar a última.
                    //s.nivelMaximo = config.UsuNivel;
                    new SolicitacaoBLL().Atualizar(s);

                    p.Solicitacao = s;
                    p.Codperusu = 2; // o perfil do analista de crédito. -> se o usuário não tiver perfil, avisar na tela.
                    p.Codusuapr = s.CodUsuarioSolicitacao; // obter o codigo do usuario da aprovacao. OK
                    //p.Datpar = historico.DatEncaminhamento;
                    p.Codsitpar = Convert.ToInt32(SituacaoParecer.AguardandoAprovacao);

                    if (!String.IsNullOrEmpty(s.TxtJustificativa))
                    {
                        parecerSolicitacaoBLL.PreencheParecerComDadosSolicitacao(p, s);
                        parecerSolicitacaoBLL.Salvar(p);

                        // Salvar o histórico da solicitação
                        historicoBLL.Salvar(historico);
                    }
                    else
                    {
                        throw new Exception("A Justificativa da Solicitação não foi encontrada.");
                    }

                    #endregion

                    // return Json(new { msg = "Envio da solicitação nº " + s.Codigo + " para aprovação foi realizado com sucesso." }, JsonRequestBehavior.DenyGet);

                    // (atualiza os grids de todos os usuários logados , sem necessidade do F5)
                    var context = GlobalHost.ConnectionManager.GetHubContext<StatusHub>();
                    context.Clients.All.AtualizarGrid();

                    return RedirectToAction("Index", "Solicitacao");

                }
                catch (Exception ex)
                {
                    return Json(new { msg = "Não foi possível enviar a Solicitação nº " + s.Codigo + " para aprovação. ERRO -> " + ex.Message }, JsonRequestBehavior.DenyGet);
                }
            }
        }
        public ActionResult SalvarParecer(DadoPrincipalAprovacao dadPri, DefinicoesClienteAprovacao defCli, string Txtpar, string StatusParecer, string chkEncerra, string vlrLimAnalise, string cpgAnalise, string fpgAnalise)
        {
            using (ParecerSolicitacaoBLL parecerSolicitacaoBLL = new ParecerSolicitacaoBLL())
            {
                PerfilUsuarioBLL perfilBLL = new PerfilUsuarioBLL();
                ConfiguracaoWorkflowBLL configBLL = new ConfiguracaoWorkflowBLL();
                HistoricoSolicitacaoBLL historicoBLL = new HistoricoSolicitacaoBLL();

                ParecerSolicitacao p = Session["Parecer"] as ParecerSolicitacao;
                Solicitacao s = Session["Solicitacao"] as Solicitacao;

                var historico = new HistoricoSolicitacao();

                var usuario = Session["ConexaoSapiens"] as UsuarioSapiens;
                List<PerfilUsuario> perfisUsuarioLogado = null;

                if (usuario != null)
                {
                    perfisUsuarioLogado = perfilBLL.ObterGruposPorCodUsuario(usuario.Codusu);
                }

                // se algum dos perfis do usuário logado contém o perfil aprovador, pode salvar parecer.
                var queryPodeSalvarParecer = from meuPerfil in perfisUsuarioLogado
                                             where meuPerfil.CodPerfilUsuario == p.Codperusu
                                             select meuPerfil;

                var podeSalvar = queryPodeSalvarParecer.Count() > 0 ? true : false;

                // Se o usuário logado não tiver o perfil de aprovação, não pode salvar o parecer
                if (!podeSalvar)
                {
                    return Json(new { msg = "O perfil atual não tem permissão para aprovar este parecer." }, JsonRequestBehavior.DenyGet);
                }

                switch (StatusParecer)
                {
                    case "AP":
                        p.Codsitpar = Convert.ToDecimal(SituacaoParecer.Aprovada);
                        break;

                    case "RP":
                        p.Codsitpar = Convert.ToDecimal(SituacaoParecer.Reprovada);
                        p.Solicitacao.Situacao = "REPROVADA";
                        historico.CodSituacaoSolicitacao = Convert.ToInt32(SituacaoParecer.Reprovada);
                        historico.DatFinalizacao = DateTime.Now;

                        break;
                }

                #region atualiza o parecer atual com os dados que estão na tela.

                SalvarDadoPrincipal(dadPri);

                defCli.VlrLimite = vlrLimAnalise;
                defCli.CodCondicaoPagamento = cpgAnalise;
                defCli.CodFormaDePagamento = fpgAnalise;

                SalvarDefinicoes(defCli);

                #endregion

                // usando o SignalR para implementar atualização geral em tempo real.
                // (atualiza os grids de todos os usuários logados , sem necessidade do F5)
                var context = GlobalHost.ConnectionManager.GetHubContext<StatusHub>();

                //o parecer persistido ( pode gravar, atualizar, até excluir pelo BLL);
                var parecer = parecerSolicitacaoBLL.ObterPorCodigo(p.CodParecer);

                parecer.Codsitpar = p.Codsitpar; // O Novo parecer inicia como Aguardando Aprovação.
                parecer.Codusuapr = usuario.Codusu;
                parecer.Datpar = DateTime.Now;
                parecer.Solicitacao = p.Solicitacao;
                parecer.Txtpar = Txtpar;

                try
                {
                    if (!String.IsNullOrEmpty(Txtpar))
                    {
                        // se entrar aqui , está APROVADA e OK para Gravar.
                        if (parecer.Codsitpar == Convert.ToDecimal(SituacaoParecer.Aprovada))
                        {
                            // verificar na configuração de alçada se tem próximo nível e qual é esse nível.
                            // 21/08/2015 - verificar se o parecer que está sendo aprovado é o último necessário

                            // se o usuário aprovador corresponde ao nivel máximo, ou se está marcado para encerrar o parecer, pode enviar...
                            var prontaParaIntegrar = (((parecer.Codperusu - 2) == s.nivelMaximo) || chkEncerra == "S");
                            //(s.PareceresSolicitacao.Count - 1) == s.nivelMaximo || chkEncerra == "S"
                            if (prontaParaIntegrar)
                            {
                                try
                                {
                                    // muda status para Aguardando integração
                                    parecer.Codsitpar = Convert.ToDecimal(SituacaoParecer.AguardandoIntegracao);
                                    parecer.Solicitacao.CodSituacaoAtual = Convert.ToInt32(SituacaoSolicitacao.AguardandoIntegracao);
                                    parecerSolicitacaoBLL.Atualizar(parecer);

                                    s.CodSituacaoAtual = Convert.ToInt32(SituacaoSolicitacao.AguardandoIntegracao);

                                    Thread t = new Thread(_ =>
                                    {
                                        ServiceReferenceTeste.srvSicadSoapClient clienteTesteIntegracao = new ServiceReferenceTeste.srvSicadSoapClient();
                                        clienteTesteIntegracao.IntegrarDadosCliente(p.Solicitacao.Codigo);
                                    });

                                    t.Start();

                                    historico.DatEncaminhamento = DateTime.Now;
                                    historico.CodSituacaoSolicitacao = Convert.ToInt32(SituacaoSolicitacao.AguardandoIntegracao);
                                    historico.Solicitacao = s;
                                    if (chkEncerra == "S")
                                    {
                                        Txtpar += " ( Encerramento do workflow antecipado por " + usuario.Nomusu + " )";
                                    }
                                    historico.TxtHistorico = Txtpar;

                                    historicoBLL.Salvar(historico);
                                }
                                catch (Exception ex)
                                {
                                    // TODO: Retirar depois de validar a execução do webservice ( vai ficar aguardando Integração se for finalmente aprovado )
                                    parecer.Codsitpar = Convert.ToDecimal(SituacaoParecer.AguardandoAprovacao);
                                    parecerSolicitacaoBLL.Atualizar(parecer);

                                    throw ex;
                                }
                            }
                            else
                            {

                                int codPerfilAprovadorAtual = Convert.ToInt32(parecer.Codperusu);

                                // se não encerra, cria um novo parecer ...
                                var novoParecer = new ParecerSolicitacao();

                                novoParecer.Solicitacao = p.Solicitacao;

                                novoParecer.Codsitpar = Convert.ToDecimal(SituacaoParecer.AguardandoAprovacao);

                                novoParecer.Codhistsol = historico.CodHistoricoSolicitacao; // pegar o codhist OK
                                //novoParecer.Codperusu = ++p.Codperusu; // o perfil do analista de crédito. -> se o usuário não tiver perfil, avisar na tela.

                                int codPerfilProximoAprovador = 0;

                                switch (codPerfilAprovadorAtual)
                                {
                                    case 2: codPerfilProximoAprovador = 3; break;
                                    case 3: codPerfilProximoAprovador = 4; break;
                                    case 4: codPerfilProximoAprovador = 5; break;

                                    //case 5: return Json("", JsonRequestBehavior.DenyGet);

                                }

                                novoParecer.Codperusu = (decimal)codPerfilProximoAprovador;
                                //novoParecer.Codusuapr = s.CodUsuarioSolicitacao; // obter o codigo do usuario da aprovacao. OK
                                novoParecer.Codusuapr = usuario.Codusu;

                                // necessário definir o código como 0 para instruir o NHibernate que este é um novo objeto.
                                dadPri.CodigoDadoPrincipalAprovacao = 0;
                                dadPri.Parecer = parecer;

                                // salvar todos os dados do parecer anterior no novo parecer, e incluir as alterações feitas na tela.
                                novoParecer.DadosPrincipaisAprovacao.Add(dadPri);

                                defCli.CodDefinicoesClienteAprovacao = 0;
                                defCli.Parecer = parecer;
                                novoParecer.DefinicoesAprovacao.Add(defCli);

                                foreach (var ca in p.CaracteristicasAprovacao)
                                {
                                    ca.CodCaracteristicaClienteAprovacao = 0;
                                    novoParecer.CaracteristicasAprovacao.Add(ca);
                                }

                                foreach (var ec in p.EnderecosCobrancaAprovacao)
                                {
                                    ec.CodEnderecoCobrancaClienteApr = 0;
                                    novoParecer.EnderecosCobrancaAprovacao.Add(ec);
                                }

                                foreach (var ee in p.EnderecosEntregaAprovacao)
                                {
                                    ee.CodEnderecoEntregaClienteApr = 0;
                                    novoParecer.EnderecosEntregaAprovacao.Add(ee);
                                }

                                foreach (var r in p.ReferenciasAprovacao)
                                {
                                    r.CodReferenciaApr = 0;
                                    novoParecer.ReferenciasAprovacao.Add(r);
                                }

                                foreach (var c in p.ContatosAprovacao)
                                {
                                    c.CodContatoAprovacao = 0;
                                    novoParecer.ContatosAprovacao.Add(c);
                                }

                                foreach (var soc in p.SociosAprovacao)
                                {
                                    soc.CodSocioEmpresaAprovacao = 0;
                                    novoParecer.SociosAprovacao.Add(soc);
                                }

                                foreach (var doc in p.DocumentosAnexadosAprovacao)
                                {
                                    doc.CodDocumentoAnexadoApr = 0;
                                    novoParecer.DocumentosAnexadosAprovacao.Add(doc);
                                }

                                // EX: se estiver R$ 5.000,00 vai ficar 5000, se for nulo vai virar string vazia
                                novoParecer.DefinicoesAprovacao.Last().VlrLimite = String.IsNullOrEmpty(novoParecer.DefinicoesAprovacao.Last().VlrLimite) ? "" : Regex.Replace(novoParecer.DefinicoesAprovacao.Last().VlrLimite, @"(\s+)|(\\+)|(\.+)|(/+)|(\-+)|(\,+)|(R+)|(\$+)", "");
                                novoParecer.DefinicoesAprovacao.Last().VlrLimite = novoParecer.DefinicoesAprovacao.Last().VlrLimite != "" ? novoParecer.DefinicoesAprovacao.Last().VlrLimite.Substring(0, novoParecer.DefinicoesAprovacao.Last().VlrLimite.Length - 2) : "";

                                // EX: se estiver R$ 5.000,00 vai ficar 5000, se for nulo vai virar string vazia
                                novoParecer.DefinicoesAprovacao.Last().VlrDescontoFinanceiro = String.IsNullOrEmpty(novoParecer.DefinicoesAprovacao.Last().VlrDescontoFinanceiro) ? "" : Regex.Replace(novoParecer.DefinicoesAprovacao.Last().VlrDescontoFinanceiro, @"(\s+)|(\\+)|(\.+)|(/+)|(\-+)|(\,+)|(R+)|(\$+)", ""); // .Substring(0, novoParecer.DefinicoesAprovacao.Last().VlrDescontoFinanceiro.Length - 2) estava assim pois inicialmente esse campo foi entendido como monetário, mas é um valor percentual,como em '33%' ou '02%'

                                // salva o novo parecer e os objetos associados.
                                parecerSolicitacaoBLL.Salvar(novoParecer);

                                // atualiza o parecer existente para aprovado
                                parecerSolicitacaoBLL.Atualizar(parecer);

                                historico.Solicitacao = p.Solicitacao;
                                historico.TxtHistorico = p.Txtpar;
                                historico.CodSituacaoSolicitacao = Convert.ToInt32(SituacaoSolicitacao.AguardandoAprovacao);
                                historicoBLL.Salvar(historico);
                            } // fim do "se não encerra"

                        } // fim do "se aprova"
                        else // se não aprova.
                        {
                            historico.DatFinalizacao = DateTime.Now;
                            historico.CodSituacaoSolicitacao = Convert.ToInt32(SituacaoSolicitacao.Reprovada);
                            p.Solicitacao.CodSituacaoAtual = Convert.ToInt32(SituacaoSolicitacao.Reprovada);
                            s.CodSituacaoAtual = Convert.ToInt32(SituacaoSolicitacao.Reprovada);
                            historico.Solicitacao = p.Solicitacao;
                            historico.TxtHistorico = Txtpar; // MOTIVO DA REPROVAÇÃO.
                            historicoBLL.SalvarOuAtualizar(historico);

                            //TODO: atualizar o código da situação da solicitação.
                            new SolicitacaoBLL().AtualizarSituacao(s.Codigo, Convert.ToInt32(SituacaoSolicitacao.Reprovada));

                            parecerSolicitacaoBLL.Atualizar(parecer);

                            context.Clients.All.AtualizarGrid();
                            return Json(new { msg = "Parecer Atualizado." }, JsonRequestBehavior.DenyGet);

                        } // fim do "se não aprova"

                        context.Clients.All.AtualizarGrid();
                        return Json(new { msg = "Parecer Atualizado." }, JsonRequestBehavior.DenyGet);
                    }
                    else
                    {
                        throw new Exception("Não foi possível obter o texto do parecer.");
                    }
                } // Fim do try

                catch (Exception ex)
                {
                    historico.Solicitacao = p.Solicitacao;
                    historico.CodSituacaoIntegracaoSolicitacao = Convert.ToInt32(SituacaoIntegracaoSolicitacao.Erro);
                    historico.CodSituacaoSolicitacao = Convert.ToInt32(SituacaoSolicitacao.AguardandoAprovacao);
                    historico.TxtHistorico = ex.Message;
                    historico.DatFinalizacao = DateTime.Now;
                    historicoBLL.Salvar(historico);

                    return Json(new { erro = "Não foi possível salvar o parecer. Detalhes : " + ex.Message }, JsonRequestBehavior.DenyGet);
                }
            }
        }