Skip to main content

Case

  • Case

Case de método muito grande e foi dividido em helpers

  • Nesse caso a ação de adicionar um usuário faz bastante coisa. Esse código foi refatorado e ficou dessa forma, mas uma forma nova de se fazer que pensei foi
    • Criar 3 classes (command)
      • Adicionar/Atualizar usuário
      • LiberarSlots - já criada
      • Adicionar/Atualizar ambiente
    • Nessas classes eu criar um destructor e retornaria as propriedades que o próximo bloco precisa, assim o código ia ficar menor e ia ser como se tivesse steps
public async Task<ICommandResult> Handle(AdicionarUsuarioCommand command)
{
if (!EstaValido(command)) return Erro();

/*BLOCO 1*/
var idContrato = command.Admin ? command.ContratoId : _user.ObterContratoId();
var contratoAtual = await _contratoRepository.ObterPorId(idContrato);
var contratoUsuarioAtual = contratoAtual.Usuarios.FirstOrDefault(u => u.Email.Equals(command.Email));

var validacaoContrato = await ValidarInconsistenciaNoContratoUsuario();
if (validacaoContrato.Invalido)
return Erro(validacaoContrato.MensagemErro);

ContratoUsuario novoContratoUsuario = AdicionarUsuarioCommandFactory.ObterNovoContratoUsuario(command, contratoUsuarioAtual);
await AdicionarUsuarioContrato();
await AtualizarUsuarioContrato();
/*BLOCO 1*/

/*BLOCO 2*/
await LiberarSlotsDasEmpresasRevogadas();
/*BLOCO 2*/

/*BLOCO 3*/
PerfilAcesso perfilAcesso = await ObterPerfilAcessoParaAtualizarFirebase();
if (perfilAcesso is null)
return Erro(Shared.Enums.MensagemErro.PERFIL_ACESSO_NAO_ENCONTRADO);

var novasEmpresasPermitidas = AdicionarUsuarioCommandFactory.ObterNovasEmpresasPermitidas(contratoAtual, command);
if (!novasEmpresasPermitidas.Any())
return Erro(Shared.Enums.MensagemErro.USUARIO_EMPRESAS_NAO_ENCONTRADAS);

var ambienteAtual = await _ambienteRepository.ObterPrimeiroAmbientePorContratoId(idContrato);
await ModificarUsuarioAmbiente();
await ModificarUsuarioAmbienteFirebase();
/*BLOCO 3*/

return Resposta();

async Task<(bool Invalido, string MensagemErro)> ValidarInconsistenciaNoContratoUsuario()
{
if (contratoAtual is null)
return (true, MensagemErro.CONTRATO_NAO_ENCONTRADO);

if (!contratoAtual.Empresas.Exists(e => e.Cnpj.Equals(_user.ObterCnpj())))
return (true, Shared.Enums.MensagemErro.CONTRATO_EMPRESA_NAO_PERTENCENTE);

if (await _contratoRepository.ExisteUsuarioEmOutroContrato(idContrato, command.Email))
return (true, Shared.Enums.MensagemErro.EMAIL_JA_UTILIZADO_EM_OUTRO_CONTRATO);

if (contratoUsuarioAtual != null && !contratoUsuarioAtual.Id.Equals(command.Id))
return (true, Shared.Enums.MensagemErro.CONTRATO_USUARIO_JA_CADASTRADO_PARA_OUTRO_ID);

return (false, string.Empty);
}

async Task AdicionarUsuarioContrato()
{
if (contratoUsuarioAtual is not null) return;
await _contratoRepository.AdicionarUsuario(contratoAtual.Id, novoContratoUsuario);
}

async Task AtualizarUsuarioContrato()
{
if (contratoUsuarioAtual is null) return;

var usuarios = contratoAtual.Usuarios.ToList();
usuarios.Remove(contratoUsuarioAtual);
usuarios.Add(novoContratoUsuario);

await _contratoRepository.AtualizarUsuarios(contratoAtual.Id, usuarios);
}

async Task LiberarSlotsDasEmpresasRevogadas()
{
if (contratoUsuarioAtual is null) return;

RemoverDispositivosDesvinculoUsuarioEmpresaCommand commandRemoverDispositivos = new(contrato: contratoAtual,
empresasNovas: command.Empresas.ToList(),
novoContratoUsuario: novoContratoUsuario,
contratoRepository: _contratoRepository);
await commandRemoverDispositivos.Executar();
}

async Task<PerfilAcesso> ObterPerfilAcessoParaAtualizarFirebase()
{
if (!command.Admin)
return await _perfilAcessoRepository.ObterPorId(command.PerfilAcessoId);

command.Empresas = contratoAtual.Empresas.Select(e => e.Cnpj);
return await _perfilAcessoRepository.ObterPerfilAdministrador(idContrato);
}

async Task ModificarUsuarioAmbiente()
{
ambienteAtual.AdicionarUsuario(new AmbienteUsuario(command.Email, novasEmpresasPermitidas.Select(e => e.Cnpj).ToList(), perfilAcesso.Id));
await _ambienteRepository.AdicionarOuAtualizar(ambienteAtual);
}

async Task ModificarUsuarioAmbienteFirebase()
{
var factoryCards = ModulosCardFactory.ConstruirCards(await _moduloRepository.ObterModulos(), perfilAcesso);

var usuarioFireBase = await _usuarioFirebase.ObterUsuarioPorEmail(command.Email);
var informacoesLojasPermitidas = novasEmpresasPermitidas.Select(e => new UsuarioLoja(e.NomeFantasia, e.Cnpj)).ToList();

UsuarioAmbienteDto usuarioAmbiente = new(informacoesLojasPermitidas, factoryCards);

await _usuarioFirebase.AdicionarOuAtualizarUsuarioAmbiente(AdicionarUsuarioCommandFactory.ObterNovoUsuario(command, usuarioAmbiente, usuarioFireBase),
AdicionarUsuarioCommandFactory.ObterNovoUsuarioAmbiente(ambienteAtual, usuarioAmbiente, perfilAcesso));
}
}

Código final ficou assim

public async Task<ICommandResult> Handle(AdicionarUsuarioCommand command)
{
if (!EstaValido(command)) return Erro();

try
{
var usuarioContratoDto = await _gravacaoUsuarioHelper.ExecutarAsync(command);
await _liberacaoSlotsHelper.ExecutarAsync(command, usuarioContratoDto);
await _gravacaoAmbienteHelper.ExecutarAsync(command, usuarioContratoDto);
}
catch (ValidacaoException validacaoException)
{
return Erro(validacaoException.Message);
}
catch
{
throw;
}

return Resposta();
}