Ir para o conteúdo principal

Migração das regras de negócio de férias do Portal do Servidor para o SID

Data de elaboração

 10/06/2022

Responsável pelo estudo

João Pedro Rocha Brito (Assessor)

José Henrique dos Santos Nogueira (Assessor)


Equipe do estudo

João Pedro Rocha Brito (Assessor)

José Henrique dos Santos Nogueira (Assessor)

José Lucas da Silva Costa (Analista de Desenvolvimento Full-Stack)

Jônatas Neves Legal (Técnico emTecnologia da Informação e Comunicação) 

Alvo Sistema Integrado de Descanso.
Origem

Implementação: Migração das regras de negócio de férias do Portal do Servidor para o SID.

Objetivo

Informar a respeito das regras de negócio que estão no Portal do Servidor e deveriam está na API do SID.
Documentação Correlata Sem documentação correlata.

Observações

Sem observações.

1. Glossário de Termos

  1. API Application Programming Interface (interface de Programação de Aplicações).
  2. SETIC - Superintendência Estadual de Tecnologia da Informação e Comunicação.
  3. SID - Sistema Integrado de Descanso.

2. Introdução - Migração das regras de negócio de férias do Portal do Servidor para o SID


Inicialmente o SID (Sistema Integrado de Descanso) é o sistema responsável pelo controle de férias do Poder Executivo Estadual, atualmente o Portal do Servidor no ato de uma solicitação de férias ou remarcação se comunica com o SID para lançamento de uma solicitação. A problemática envolve informar tratar a respeito das regras de negócio que estão no Portal do Servidor e deveriam está na API do SID.

3. Desenvolvimento


Inicialmente vamos introduzir o que é regra de negócio, as regras de negócio são declarações que vão orientar o bom funcionamento do negócio. Eles podem ser simples, ou mais complexos, envolvendo até mesmo regras de lógica. Mas elas tem a função de definir basicamente o que, onde, quando, por que e como algo deve ser feito dentro de um sistema. Atualmente existem várias regras de negócio que estão no Portal do Servidor e que algumas até falham fazendo com que os dados do banco de dados não possua consistência, vejamos um trecho de código a seguir do Portal do Servidor:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using PortalDoServidor.AppService.Interface;
using PortalDoServidor.AppService.ViewModel.Ferias;
using PortalDoServidor.CrossCutting.Services.Dto;
using PortalDoServidor.CrossCutting.Services.Enumerables;
using PortalDoServidor.CrossCutting.Services.Interface;
using PortalDoServidor.CrossCutting.Services.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PortalDoServidor.Apresentacao.Controllers
{
    [Authorize]
    public class FeriasController : Controller
    {
        private readonly IUserService userService;
        private readonly IFeriasAppService feriasAppService;
        private readonly IApiServicos apiServicos;
        private readonly IServicoAppService servicoAppService;
        private readonly IColaboradorAppService colaboradorAppService;

        public FeriasController(IUserService userService, IFeriasAppService feriasAppService, IApiServicos apiServicos, IServicoAppService servicoAppService, IColaboradorAppService colaboradorAppService)
        {
            this.userService = userService;
            this.feriasAppService = feriasAppService;
            this.apiServicos = apiServicos;
            this.servicoAppService = servicoAppService;
            this.colaboradorAppService = colaboradorAppService;
        }

        public async Task<IActionResult> Index()
        {
            var cpfDoColaborador = userService.ObterCpf();
            var matriculaDoColaborador = userService.ObterMatricula();
            var nomeDoColaborador = userService.ObterNome();
            var cargo = userService.ObterCargo();

            var feriasViewModel = await feriasAppService.BuscarSolicitacoesDeFeriasViewModel(cpfDoColaborador);

            if (cargo.Contains("TÉCNICO EM RADIOLOGIA"))
                feriasViewModel.EhTecnicoEmRadiologia = true;

            ViewData["Colaborador"] = nomeDoColaborador;
            ViewData["PossuiFeriasPendentes"] = await feriasAppService.VerificarSePossuiFeriasPendentes(cpfDoColaborador);

            return View(feriasViewModel);
        }

        public async Task<IActionResult> SolicitacoesDoColaborador()
        {
            var cpfDoColaborador = userService.ObterCpf();
            var solicitacoes = await feriasAppService.BuscarSolicitacoesDeFeriasDoColaborador(cpfDoColaborador);
            return View(solicitacoes);
        }

        public async Task<IActionResult> SolicitacoesDosServidoresDoDepartamento(int? solicitacaoAnoDeExercicio)
        {
            var cpfDoServidor = userService.ObterCpf();
            int anoDeExercicio = solicitacaoAnoDeExercicio ?? DateTime.Now.AddYears(1).Year;
            var solicitacoes = await feriasAppService.BuscarSolicitacoesDeFeriasDoDepartamentoDoUsuario(cpfDoServidor, anoDeExercicio);

            ViewData["AnoDeExercicio"] = anoDeExercicio;
            ViewData["PeriodoDePlanejamentoDeFerias"] = await feriasAppService.BuscarPeriodoDePlanejamentoDeFerias();
            return View(solicitacoes);
        }

        public async Task<IActionResult> Cadastrar(Guid solicitacaoId, string codigoUnidadeOrcamentaria)
        {

            var periodoDePlanejamento = await feriasAppService.BuscarPeriodoDePlanejamentoDeFerias();

            var cpfDoColaborador = userService.ObterCpf();

            CarregarViewBagDasMatriculasDoServidor();
            var podeSolicitarFerias = await feriasAppService.VerificarSePodeSolicitarFerias(cpfDoColaborador);

            if (!podeSolicitarFerias)
            {
                TempData["Erro"] = "Servidor já possui férias marcadas!";
                return RedirectToAction("Detalhes", "Servico", new { Id = solicitacaoId, codigoUnidadeOrcamentaria });
            }

            if (!periodoDePlanejamento.PodePlanejar)
            {
                TempData["Erro"] = "O planejamento de férias expirou!";
                return RedirectToAction("Detalhes", "Servico", new { Id = solicitacaoId, codigoUnidadeOrcamentaria });
            }

            return View();
        }


        public async Task<IActionResult> CadastrarDaMatricula(string matriculaDoColaborador)
        {
            CarregarViewBagDasMatriculasDoServidor(matriculaDoColaborador);

            var periodoDisponivelParaOServidorMarcarAsFerias = await feriasAppService.ObterPeriodoDisponivelParaOServidorMarcarAsFerias(matriculaDoColaborador, 0);

            ViewData["AtividadePrivativaDoCargoDeRaioXValido"] = false;

            var cargo = await apiServicos.ObterCargo(matriculaDoColaborador);

            if (ValidarCargo.DeProcurador(cargo))
            {
                var quantidadeDeSolicitacoes = await feriasAppService.ObterQuantidadeDeSolicitacaoesRealizadasParaOAnoEmExercicio(matriculaDoColaborador);
                ViewData["EhProcurador"] = true;
                ViewData["QuantidadeDeSolicitacoes"] = quantidadeDeSolicitacoes + 1;
            }
            else if (cargo.Contains("TÉCNICO EM RADIOLOGIA") || cargo.Contains("TÉCNICO EM RADIOTERAPIA"))
            {
                ViewData["AtividadePrivativaDoCargoDeRaioXValido"] = await feriasAppService.VerificarCargoDeTecnicoEmRadiologiaOuRadioterapia(matriculaDoColaborador);
            }
            else if (cargo.Contains("PROFESSOR CLASSE A") || cargo.Contains("PROFESSOR CLASSE B") || cargo.Contains("PROFESSOR CLASSE C"))
            {
                ViewData["AtividadePrivativaDoCargoDeProfessorComFeriasAutomaticas"] = await feriasAppService.VerificarCargoDoProfessorSePossuiFeriasAutomaticas(matriculaDoColaborador);
            }

            var anoAquisitivo = periodoDisponivelParaOServidorMarcarAsFerias.DataInicial.AddYears(-1).Year;

            ViewData["CargoDoServidor"] = cargo;
            ViewData["Matricula"] = matriculaDoColaborador;
            ViewData["AnoAquisitivo"] = anoAquisitivo;
            ViewData["DataInicial"] = periodoDisponivelParaOServidorMarcarAsFerias.DataInicial;
            ViewData["DataFinal"] = periodoDisponivelParaOServidorMarcarAsFerias.DataFinal;

            return View("CamposDoCadastroDeFerias");
        }

        public async Task<IActionResult> ServicoDeRemarcacaoDeFerias()
        {
            var cpfDoColaborador = userService.ObterCpf();
            var feriasViewModel = await feriasAppService.BuscarSolicitacoesDeFeriasViewModel(cpfDoColaborador);
            feriasViewModel.UnidadeOrcamentariaId = colaboradorAppService.ObterTodasAsUnidadesOrcamentariasDoColaborador(cpfDoColaborador).Result.FirstOrDefault();
            return View(feriasViewModel);
        }

        [HttpPost]
        public async Task<IActionResult> Cadastrar(string formaDoPeriodoDeFerias, List<PeriodoDeFeriasDto> dataInicialDeFerias, int anoAquisitivo, string matricula)
        {
            CarregarViewBagDasMatriculasDoServidor();

            var response = await feriasAppService.EnviarSolicitacaoDeFerias(formaDoPeriodoDeFerias, matricula, dataInicialDeFerias, anoAquisitivo);

            if (response.Success)
            {
                TempData["Sucesso"] = response.Message;
                return RedirectToAction("Solicitacoes", "Servico");
            }
            else
            {
                TempData["Erro"] = response.Message;
            }

            return RedirectToAction();
        }

        public async Task<IActionResult> Editar(int id, string codigoUnidadeOrcamentaria, string matriculaDoServidor)
        {

            var solicitacao = await feriasAppService.ObterSolicitacaoDeFerias(id, matriculaDoServidor);

            PeriodoDisponivelDTO periodoDisponivelParaOServidorMarcarAsFerias = null;

            if (solicitacao.Remarcacao)
            {
                periodoDisponivelParaOServidorMarcarAsFerias = await feriasAppService.ObterPeriodoDisponivelParaOServidorRemarcarAsFeriasPendentes();
            }
            else
            {
                periodoDisponivelParaOServidorMarcarAsFerias = await feriasAppService.ObterPeriodoDisponivelParaOServidorMarcarAsFerias(matriculaDoServidor, id);
            }

            ViewData["DataInicial"] = periodoDisponivelParaOServidorMarcarAsFerias.DataInicial;
            ViewData["DataFinal"] = periodoDisponivelParaOServidorMarcarAsFerias.DataFinal;
            ViewData["CodigoUnidadeOrcamentaria"] = codigoUnidadeOrcamentaria;

            return View(solicitacao);
        }

        [HttpPost]
        public async Task<IActionResult> Editar(int id, string formaDoPeriodoDeFerias, List<PeriodoDeFeriasDto> dataInicialDeFerias, int anoAquisitivo, bool remarcacao, int quantidadeDeDiasPendentes, string codigoUnidadeOrcamentaria, string matricula)
        {

            var response = await feriasAppService.EnviarSolicitacaoDeFerias(id, formaDoPeriodoDeFerias, matricula, dataInicialDeFerias, anoAquisitivo, remarcacao, quantidadeDeDiasPendentes);

            if (response.Success)
            {
                TempData["Sucesso"] = response.Message;
                return RedirectToAction("SolicitacaoDeServico", "Servico",
                    new { response.Id, codigoUnidadeOrcamentaria, origem = OrigemDaSolicitacao.SidSolicitacao });
            }
            else
            {
                TempData["Erro"] = response.Message;
            }

            return RedirectToAction("Solicitacoes", "Servico");
        }

        [HttpPost]
        public async Task<IActionResult> DarCienciaDeNotificacaoDeFerias(int id)
        {
            var response = await feriasAppService.DarCienciaDeNotificacaoDeFerias(id);

            if (response.Success)
            {
                return RedirectToAction(nameof(Index));
            }

            return RedirectToAction(nameof(Index));
        }

        public async Task<IActionResult> DetalhesDaSuspensao(int suspensaoId)
        {
            var suspensao = await feriasAppService.BuscarSolicitacaoDeSuspensaoDoColaboradorPorId(suspensaoId);

            return PartialView("_DetalhesDaSuspensao", suspensao);
        }

        public async Task<IActionResult> DetalhesDaInterrupcao(int interrupcaoId)
        {
            var interrupcao = await feriasAppService.BuscarSolicitacaoDeInterrupcaoDoColaboradorPorId(interrupcaoId);

            return PartialView("_DetalhesDaInterrupcao", interrupcao);
        }

        public async Task<IActionResult> DarCienciaNaSuspensao(int id, string codigoUnidadeOrcamentaria, int solicitacaoDeferiasId)
        {
            var response = await feriasAppService.DarCienciaNaSuspensao(id);

            if (response.Success)
            {
                TempData["Sucesso"] = response.Message;
            }
            else
            {
                TempData["Erro"] = response.Message;
            }

            return RedirectToAction("SolicitacaoDeServico", "Servico",
                     new { id = solicitacaoDeferiasId, codigoUnidadeOrcamentaria, origem = OrigemDaSolicitacao.SidSolicitacao });
        }

        public async Task<IActionResult> DarCienciaNaInterrupcao(int id, string codigoUnidadeOrcamentaria, int solicitacaoDeferiasId)
        {
            var response = await feriasAppService.DarCienciaNaInterrupcao(id);

            if (response.Success)
            {
                TempData["Sucesso"] = response.Message;
            }
            else
            {
                TempData["Erro"] = response.Message;
            }
            return RedirectToAction("SolicitacaoDeServico", "Servico",
                    new { id = solicitacaoDeferiasId, codigoUnidadeOrcamentaria, origem = OrigemDaSolicitacao.SidSolicitacao });
        }

        public async Task<IActionResult> SolicitarRemarcacaoDeFerias(int solicitacaoId, string codigoUnidadeOrcamentaria)
        {
            var motivosDaRemarcacaoDeFerias = await feriasAppService.BuscarOsMotivosDaRemarcacaoDeFerias();
            ViewBag.Motivos = new SelectList(motivosDaRemarcacaoDeFerias, "Descricao", "Descricao");
            ViewData["SolicitacaoId"] = solicitacaoId;
            ViewData["CodigoUnidadeOrcamentaria"] = codigoUnidadeOrcamentaria;
            return View();
        }

        public async Task<IActionResult> SolicitarRemarcacaoDeFeriasInrrompidas(int solicitacaoId, string codigoUnidadeOrcamentaria)
        {
            var periodosDisponiveis = await feriasAppService.ObterPeriodosDeFeriasDisponiveisParaRemarcar(solicitacaoId);


            ViewData["SolicitacaoId"] = solicitacaoId;

            ViewData["CodigoUnidadeOrcamentaria"] = codigoUnidadeOrcamentaria;


            ViewData["DataInicial"] = DateTime.Now.AddDays(1);
            ViewData["DataFinal"] = new DateTime(DateTime.Now.Year, 12, 31);

            ViewData["CodigoUnidadeOrcamentaria"] = codigoUnidadeOrcamentaria;

            return View(periodosDisponiveis);
        }
        [HttpPost]
        public async Task<IActionResult> RemarcarFeriasInterrompidas(ReceberDadosDaRemarcacao receberDadosDaRemarcacao)
        {
            receberDadosDaRemarcacao.EhRemarcacaoDeInterrupcao = true;
            var response = await feriasAppService.EnviarSolicitacaoDeRemarcacaoDeFerias(receberDadosDaRemarcacao);
            if (response.Success)
            {
                TempData["Sucesso"] = response.Message;
                return RedirectToAction("SolicitacaoDeServico", "Servico",
                    new { Id = receberDadosDaRemarcacao.SolicitacaoDeFeriasId, codigoUnidadeOrcamentaria = receberDadosDaRemarcacao.CodigoUnidadeOrcamentaria, origem = OrigemDaSolicitacao.SidSolicitacao });
            }
            else
            {
                TempData["Erro"] = response.Message;
                return RedirectToAction(nameof(RemarcarFerias), new { solicitacaoId = receberDadosDaRemarcacao.SolicitacaoDeFeriasId, codigoUnidadeOrcamentaria = receberDadosDaRemarcacao.CodigoUnidadeOrcamentaria, motivo = receberDadosDaRemarcacao.Motivo });
            }
        }

        public async Task<IActionResult> RemarcarFerias(int solicitacaoId, string codigoUnidadeOrcamentaria, string motivo)
        {
            var periodosDisponiveis = await feriasAppService.ObterPeriodosDeFeriasDisponiveisParaRemarcar(solicitacaoId);

            var motivosDaRemarcacaoDeFerias = await feriasAppService.BuscarOsMotivosDaRemarcacaoDeFerias();

            ViewBag.Motivos = new SelectList(motivosDaRemarcacaoDeFerias, "Descricao", "Descricao", motivo);

            var periodoDisponivelParaOServidorMarcarAsFerias = await feriasAppService.ObterPeriodoDisponivelParaOServidorRemarcarAsFerias(solicitacaoId, motivo);
            var ehRemacarcacaoDeVinteMaisDezDias = VerficarSeEhRemarcacaoDeVinteMaisDezDias(periodosDisponiveis.FormaDoPeriodoDeFerias, periodosDisponiveis, motivo);

            if (ehRemacarcacaoDeVinteMaisDezDias && (periodosDisponiveis.PeriodosDeFerias[0].TipoDoPeriodoDeFerias.Equals("DezDias") && !periodosDisponiveis.PeriodosDeFerias[0].PodeRemarcar))
            {
                ViewData["GozouDezDias"] = true;
            }
            ViewData["SolicitacaoId"] = solicitacaoId;
            ViewData["EhRemarcacaoDeVinteMaisDezDias"] = ehRemacarcacaoDeVinteMaisDezDias;
            ViewData["CodigoUnidadeOrcamentaria"] = codigoUnidadeOrcamentaria;
            ViewData["AbonoGozado"] = periodosDisponiveis.VerificarSeJaGozouDoAbono();
            ViewData["Motivo"] = motivo;
            ViewData["DataInicial"] = periodoDisponivelParaOServidorMarcarAsFerias.DataInicial;
            ViewData["DataFinal"] = periodoDisponivelParaOServidorMarcarAsFerias.DataFinal;
            var jaVeioComAbonoQueNaoPodeRemarcar = periodosDisponiveis.PeriodosDeFerias.Any(x => x.TipoDoPeriodoDeFerias.Equals("Abono") && !x.PodeRemarcar);
            ViewData["JaTemAbonoENaoPodeRemarcar"] = jaVeioComAbonoQueNaoPodeRemarcar;
            return View(periodosDisponiveis);
        }

        [HttpPost]
        public async Task<IActionResult> RemarcarFerias(ReceberDadosDaRemarcacao receberDadosDaRemarcacao, string jatemAbono)
        {
            if (receberDadosDaRemarcacao.Motivo.ToUpper() != "SEM MOTIVO" && string.IsNullOrEmpty(receberDadosDaRemarcacao.NumeroDoProcessoSei))
                return MensagemErro("Por favor, informe o numero do processo do SEI.");

            if (ValidarDados())
            {
                var response = await feriasAppService.EnviarSolicitacaoDeRemarcacaoDeFerias(receberDadosDaRemarcacao);

                if (response.Success)
                    return MensagemSucesso(response.Message);
                else
                    return MensagemErro(response.Message);
            }

            return MensagemErro("A Data do abono não pode ser menor que 60 dias, contando a partir de hoje");

            bool ValidarDados()
            {
                var podeProceguir = true;
                var temAbonoNoPlanejamentoAnual = !string.IsNullOrEmpty(jatemAbono) && jatemAbono.Equals("jaTemAbono");
                if (receberDadosDaRemarcacao.DataInicialDeFerias.Any(x => x.TipoDoPeriodoDeFerias.Equals("Abono")) && !temAbonoNoPlanejamentoAnual)
                {
                    var dataModelo = DateTime.Now.AddDays(60).Date;
                    var periodoDeAbono = receberDadosDaRemarcacao.DataInicialDeFerias.FirstOrDefault(x => x.TipoDoPeriodoDeFerias.Equals("Abono"));
                    podeProceguir = periodoDeAbono.DataInicial.Date >= dataModelo;
                }

                return podeProceguir;
            }

            IActionResult MensagemSucesso(string mensagem) 
            {
                TempData["Sucesso"] = mensagem;
                return RedirectToAction("SolicitacaoDeServico", "Servico", new
                {
                    Id = receberDadosDaRemarcacao.SolicitacaoDeFeriasId,
                    codigoUnidadeOrcamentaria = receberDadosDaRemarcacao.CodigoUnidadeOrcamentaria,
                    origem = OrigemDaSolicitacao.SidSolicitacao
                });
            }

            IActionResult MensagemErro(string mensagem)
            {
                TempData["Erro"] = mensagem;
                return RedirectToAction(nameof(RemarcarFerias), new
                {
                    solicitacaoId = receberDadosDaRemarcacao.SolicitacaoDeFeriasId,
                    codigoUnidadeOrcamentaria = receberDadosDaRemarcacao.CodigoUnidadeOrcamentaria,
                    motivo = receberDadosDaRemarcacao.Motivo
                });
            }
        }

        public IActionResult ObterPartialDaformaDoPeriodoDeFerias(string idSolicitacao, string formaDoPeriodoDeFerias, string motivo)
        {
            var periodosDisponiveis = feriasAppService.ObterPeriodosDeFeriasDisponiveisParaRemarcar(int.Parse(idSolicitacao)).Result;

            if (VerficarSeEhRemarcacaoDeVinteMaisDezDias(formaDoPeriodoDeFerias, periodosDisponiveis, motivo))
            {
                if (formaDoPeriodoDeFerias.Equals("TresDeDezDias"))
                {
                    if (!string.IsNullOrEmpty(motivo) && !motivo.Equals("SEM MOTIVO"))
                    {
                        formaDoPeriodoDeFerias = "TresDeDezDiasComMotivo";
                    }
                    else
                    {
                        formaDoPeriodoDeFerias = "TresDeDezDias";
                    }
                    periodosDisponiveis.FormaDoPeriodoDeFerias = "TresDeDezDias";
                }
                if (formaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEDezDiasDeAbono"))
                {
                    formaDoPeriodoDeFerias = "UmaDeVinteDiasEDezDiasDeAbono";
                    periodosDisponiveis.FormaDoPeriodoDeFerias = "UmaDeVinteDiasEDezDiasDeAbono";
                }
                if (formaDoPeriodoDeFerias.Equals("DoisDeDezDiasEUmAbonoDeDezDias"))
                {
                    formaDoPeriodoDeFerias = "DoisDeDezDiasEUmAbonoDeDezDias";
                    periodosDisponiveis.FormaDoPeriodoDeFerias = "DoisDeDezDiasEUmAbonoDeDezDias";
                }
                if (formaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEOutraDezDias"))
                {
                    formaDoPeriodoDeFerias = "UmaDeVinteDiasEOutraDezDias";
                    periodosDisponiveis.FormaDoPeriodoDeFerias = "UmaDeVinteDiasEOutraDezDias";
                }
                ViewData["RemacarcaoVinteDias"] = true;
                ViewData["AbonoGozado"] = periodosDisponiveis.VerificarSeJaGozouDoAbono();
                return PartialView($"_{formaDoPeriodoDeFerias}", periodosDisponiveis);
            }
            if (VerificarSeEhRemarcacaoTresDeDezDias(periodosDisponiveis))
            {
                ViewData["RemacarcaoTresDeDezDias"] = true;
                ViewData["RemacarcaoVinteDias"] = false;
                ViewData["AbonoGozado"] = periodosDisponiveis.VerificarSeJaGozouDoAbono();
                return PartialView($"_{formaDoPeriodoDeFerias}", periodosDisponiveis);
            }
            if ((!string.IsNullOrEmpty(motivo) && !motivo.Equals("SEM MOTIVO")) && (periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEOutraDezDias") && periodosDisponiveis.PeriodosDeFerias.Count(x => !x.PodeRemarcar) == 1))
            {
                if (!periodosDisponiveis.PodeConverterEmAbonoEhRemarcarDezDias())
                {
                    formaDoPeriodoDeFerias = "DoisDeDezDiasEDezDiasDeAbonoComMotivo";
                    return PartialView($"_{formaDoPeriodoDeFerias}", periodosDisponiveis);
                }
            }
            if ((!string.IsNullOrEmpty(motivo) && !motivo.Equals("SEM MOTIVO")) && (periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEDezDiasDeAbono") && periodosDisponiveis.PeriodosDeFerias.Any(x => !x.PodeRemarcar && x.TipoDoPeriodoDeFerias.Equals("Abono"))))
            {
                ViewData["JaGozouOuNaoPodeRemarcarOAbono"] = true;
                formaDoPeriodoDeFerias = "DoisDeDezDiasEDezDiasDeAbonoComMotivo";
                return PartialView($"_{formaDoPeriodoDeFerias}", periodosDisponiveis);
            }

            ViewData["RemacarcaoTresDeDezDias"] = false;
            ViewData["AbonoGozado"] = periodosDisponiveis.VerificarSeJaGozouDoAbono();
            ViewBag.SelecioneiOpcaoComAbono = true;
            ViewData["DataInicialParaAbonoComMotivo"] = DateTime.Now.AddDays(59);

            return PartialView($"_{formaDoPeriodoDeFerias}");
        }

        private bool VerificarSeEhRemarcacaoTresDeDezDias(RemarcarFeriasViewModel periodosDisponiveis)
        {
            if (periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("TresDeDezDias") || periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("DoisDeDezDiasEUmAbonoDeDezDias"))
            {
                if ((periodosDisponiveis.PeriodosDeFerias[0].TipoDoPeriodoDeFerias == "DezDias" && periodosDisponiveis.PeriodosDeFerias[1].TipoDoPeriodoDeFerias == "DezDias" && periodosDisponiveis.PeriodosDeFerias[2].TipoDoPeriodoDeFerias == "DezDias") && periodosDisponiveis.PeriodosDeFerias.Count(x => x.PodeRemarcar) <= 2)
                {
                    return true;
                }
                if (periodosDisponiveis.VerificarSeJaGozouDoAbono())
                {
                    return true;
                }
                return false;
            }
            return false;
        }

        private bool VerficarSeEhRemarcacaoDeVinteMaisDezDias(string formaDoPeriodoDeFerias, RemarcarFeriasViewModel periodosDisponiveis, string motivo)
        {
            if (formaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEOutraDezDias") && periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEOutraDezDias"))
            {
                if (periodosDisponiveis.PeriodosDeFerias[0].PodeRemarcar && periodosDisponiveis.PeriodosDeFerias[1].PodeRemarcar)
                {
                    return false;
                }
                return true;
            }
            else if (formaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEDezDiasDeAbono"))
            {
                return periodosDisponiveis.PeriodosDeFerias.Any(x => (!x.PodeRemarcar && x.TipoDoPeriodoDeFerias.Equals("Abono")) || (x.TipoDoPeriodoDeFerias.Equals("VinteDias") && !x.PodeRemarcar));
            }
            else if (formaDoPeriodoDeFerias.Equals("DoisDeDezDiasEUmAbonoDeDezDias"))
            {
                if ((periodosDisponiveis.PeriodosDeFerias.Count(x => !x.PodeRemarcar && x.TipoDoPeriodoDeFerias.Equals("Abono")) == 1) &&
                    (periodosDisponiveis.PeriodosDeFerias.Count(x => x.PodeRemarcar && x.TipoDoPeriodoDeFerias.Equals("DezDias")) == 2))
                {
                    return true;
                }
                if (periodosDisponiveis.PeriodosDeFerias.Count(x => !x.PodeRemarcar && x.TipoDoPeriodoDeFerias.Equals("Abono")) == 1 && periodosDisponiveis.PeriodosDeFerias.Count(x => x.PodeRemarcar && x.TipoDoPeriodoDeFerias.Equals("VinteDias")) == 1)
                {
                    return true;
                }
                else if (periodosDisponiveis.PeriodosDeFerias.Any(x => (x.TipoDoPeriodoDeFerias.Equals("DezDias") && !x.PodeRemarcar)))
                {
                    if (periodosDisponiveis.PeriodosDeFerias.Any(x => x.TipoDoPeriodoDeFerias.Equals("VinteDias") && x.PodeRemarcar))
                    {
                        return true;
                    }

                }
                return false;
            }
            if (formaDoPeriodoDeFerias.Equals("TresDeDezDias") && periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("TresDeDezDias"))
            {
                if (periodosDisponiveis.PeriodosDeFerias[0].PodeRemarcar && periodosDisponiveis.PeriodosDeFerias[1].PodeRemarcar && periodosDisponiveis.PeriodosDeFerias[2].PodeRemarcar)
                {
                    return false;
                }
                return true;
            }
            if (formaDoPeriodoDeFerias.Equals("TresDeDezDias") && periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEOutraDezDias"))
            {
                if (periodosDisponiveis.PeriodosDeFerias.Any(x => x.TipoDoPeriodoDeFerias.Equals("VinteDias") && x.PodeRemarcar))
                {
                    return true;
                }
                return false;
            }
            if (formaDoPeriodoDeFerias.Equals("DoisDeQuinzeDias") && periodosDisponiveis.FormaDoPeriodoDeFerias.Equals("DoisDeQuinzeDias"))
            {
                if (periodosDisponiveis.PeriodosDeFerias.Count(x => x.PodeRemarcar) == 2)
                {
                    return false;
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        public async Task<IActionResult> FeriasPendentes()
        {
            
            var cpfDoColaborador = userService.ObterCpf();
            var nomeDoColaborador = userService.ObterNome();

            ViewData["Colaborador"] = nomeDoColaborador;

            var feriasPendentes = await feriasAppService.BuscarFeriasPendentesDoServidor(cpfDoColaborador);

            return View(feriasPendentes);
        }

        public async Task<IActionResult> ObterSolicitacaoComPeriodosDeFeriasDoServidorParaSuspensao(int solicitacaoId)
        {
            var solicitacao = await feriasAppService.BuscarSolicitacaoPorIdParaSuspensao(solicitacaoId);
            return Json(solicitacao);
        }

        [HttpPost]
        public async Task<IActionResult> SolicitarSuspensaoDePeriodosDeFeriasDoServidor(SolicitacaoDeParalisacaoDeFeriasDto solicitacao)
        {
            var resposta = await feriasAppService.SolicitarSuspensaoDePeriodoDeFerias(solicitacao);

            if (resposta.Success)
                TempData["Sucesso"] = resposta.Message;
            else
                TempData["Erro"] = resposta.Message;

            return RedirectToAction("Solicitacoes", "Servico");
        }

        public void CarregarViewBagDasMatriculasDoServidor(string matricula = null)
        {
            var pisPasep = userService.ObterPis();
            var matriculasDoColaborador = apiServicos.ObterMovimentacaoDoServidorDtoPisPasep(pisPasep).Result;
            bool matriculaPodeSolicitarFerias = false;

            var listaDeMatriculas = matriculasDoColaborador.Select(x => new { matricula = x.matricula, descricao = string.Format("{0} | {1}", x.matricula, x.nomeDoDepartamento) });
            if (matricula == null)
                ViewBag.Matriculas = new SelectList(listaDeMatriculas, "matricula", "descricao");
            else
            {
                ViewBag.Matriculas = new SelectList(listaDeMatriculas, "matricula", "descricao", matricula);
                matriculaPodeSolicitarFerias = apiServicos.VerificarSeOServidorPodeSolicitarFerias(matricula).Result;
                ViewBag.MatriculaPodeSolicitarFerias = matriculaPodeSolicitarFerias;
            }
        }
        public IActionResult ObterPartialDoPeriodoDeTempoParaMarcacaoDeFerias(string formaDoPeriodoDeFerias)
        {
            if (formaDoPeriodoDeFerias.Equals("UmaDeVinteDiasEOutraDezDias"))
            {
                ViewData["RemacarcaoVinteDias"] = false;
                ViewData["RemacarcaoTresDeDezDias"] = false;
            }

            return PartialView($"_{formaDoPeriodoDeFerias}");
        }
    }

}

Se reparmos a linha 107, é possivel observar que existem validações de cargos com férias especiais, tais regras deveriam está no SID e não no Portal do Servidor. Outra regra que está sendo implementada pelo Portal do servidor começa pela linha 390, que é me verificação de formas de períodos e também de quando a solicitação é sem motivo ou com motivo.

Outra situação que não pode acontecer é quando as definições forem armazenadas no nível do banco de dados, esse não será o modelo de implantação ideal. A desvantagem de implantar regras no nível de banco de dados é que todos os fornecedores de banco de dados têm suas próprias maneiras proprietárias de implementar gatilhos e procedimentos armazenados.

A SETIC evita o aprisionamento de banco de dados injetando as regras na camada de aplicação, mas todos os programas têm código-fonte individual, o que pode levar a inconsistências e dificuldade de gerenciamento de código, principalmente quando um sistema igual o Portal do Servidor assume a responsabilidade de outro sistema quanto as regras de negócio.

O modelo de implantação ideal é por meio de uma camada de serviços de dados independente, na qual o Mecanismo de Regras de Negócios é acoplado livremente ao banco de dados e às camadas de aplicativos. Esse benefício de arquitetura permite que as alterações feitas sejam aplicadas automaticamente sem alterações ou recompilação.

3.1. Possíveis problemas

Atualmente o time Titãs vem recebendo diversos chamados de inconsistências causadas pelas regras que falharam no Portal do Servidor, o caso mais recente envolve um colaborador, que conseguiu marcar as férias, cujo um dos períodos do tipo abono possuía 30 dias de férias. Uma falha bem grave já que ainda envolve uma informação para pagamento para servidores que vendem suas férias. Existem também outros tipos de problemas que foram relatados, como por exemplo: Solicitações com períodos incompletos ou informações importantes ausentes na solicitação.

3.2. Valor agregado

Ao implementar um mecanismo central de regras de negócios, levará o SID para mais agilidade e eficiência a um novo nível. Quando as regras de negócio estiverem centralizadas no SID, a partir daí, poderão serem implantadas para consumo por qualquer aplicativo e processo, inclusive o Portal do Servidor. A migração das regras do Portal do Servidor trará uma série de benefícios, dentre elas, facilidade de manutenção para a equipe, redução no número de chamados já que as regras no Portal do Servidor não serão mas soberanas e também trará uma melhor experiência para o usuário final.

4. Conclusão


O presente ESTUDO TÉCNICO PRELIMINAR, elaborado pelos integrantes TÉCNICOS do time TITÃS, considerando a análise dos desafios técnicos envolvidos e citados, conclui pela VIABILIDADE DA MIGRAÇÃO DAS REGRAS DE NEGÓCIO DO PORTAL DO SERVIDOR PARA O SID DE MODO CRITERIOSO, uma vez que foram considerados os potenciais benefícios em termos de eficiência e também os problemas envolvidos, principalmente potenciais problemas. Em complemento, os contratempos identificados são administráveis, pelo que RECOMENDAMOS o prosseguimento da demanda. Ressalva-se que o ideal é a migração acontece de forma gradual, até que todas as regras sejam migradas.