public GetCandidatosResponse GetCandidatosCandidatura(DataTableRequest request, bool contarCandidaturas = true)
        {
            var response = new GetCandidatosResponse();

            try
            {
                var candidatosDescartados          = GetCandidatosDescartados();
                var candidatosBecasAbiertas        = GetCandidatosEnBecasAbiertas();
                var candidatosCandidaturasAbiertas = GetCandidatosEnCandidaturasAbiertas();
                var candidatosOmitir = candidatosCandidaturasAbiertas.Union(candidatosBecasAbiertas).Union(candidatosDescartados).Distinct().ToList();

                var query = FilterString(request.CustomFilters);

                //si buscamos desde candidatos no es necesario buscar los que tienen becas y candidaturas abiertas
                if (!contarCandidaturas)
                {
                    //Es necesario convertir a lista para optimizar rendimiento en 10 segundos en prod.
                    query = query.ToList().Where(x => !candidatosOmitir.Contains(x.CandidatoId)).AsQueryable();
                }

                var filtered = query.ApplyColumnSettings(request, CandidatoMapper.GetPropertiePath);

                IDictionary <Candidato, GetDatosByCandidatoIdResponse> relacionCandidatoCandidatura = new Dictionary <Candidato, GetDatosByCandidatoIdResponse>();


                if (contarCandidaturas) //Esto sólo ocurre si buscamos desde candidatos, porque necesitamos saber el total de candidaturas que tiene un candidato
                {
                    foreach (var candidato in filtered)
                    {
                        relacionCandidatoCandidatura[candidato] = GetDatosByCandidatoId(candidato.CandidatoId);
                    }
                    response.CandidatoRowViewModel = relacionCandidatoCandidatura.ConvertToCandidatoRowViewModel(candidatosOmitir);
                }
                else //Esto ocurre desde el buscador de candidatos de candidaturas, donde no mostramos dicha cifra.
                {
                    response.CandidatoRowViewModel = filtered.ConvertToCandidatoRowViewModel();
                }

                foreach (var candidato in response.CandidatoRowViewModel)
                {
                    if (_candidaturaRepository.Contains(x => x.IsActivo && x.CandidatoId == candidato.CandidatoId))
                    {
                        candidato.ExistenCandidaturas = true;
                    }
                    if (_becarioRepository.Contains(x => x.IsActivo && x.CandidatoId == candidato.CandidatoId))
                    {
                        candidato.ExistenBecarios = true;
                    }
                }

                response.TotalElementos = query.Count();

                response.IsValid = true;
            }
            catch (Exception ex)
            {
                response.IsValid      = false;
                response.ErrorMessage = ex.Message;
            }
            if (contarCandidaturas) //Igual que antes, sólo necesitamos la información del curriculum si buscamos desde Candidatos
            {
                foreach (var candidato in response.CandidatoRowViewModel)
                {
                    int id      = candidato.CandidatoId;
                    var tieneCv = TieneCVEnBD(id); //Se hace aparte para no hacer consultas extra en el mapper en caso de que el usuario este buscando desde el buscador de candidatos de candidatura
                    candidato.CVAvailable = tieneCv.IsValid;
                }
            }
            return(response);
        }