public ExcelIssue CadastrarIssue(ExcelIssue atualExcelIssue, bool atualizarProjetoExistente)
        {
            Issue issueLoaded = null;
            Issue issueNew;
            Issue issueToSave = null;

            issueNew = new Issue
            {
                Id = atualExcelIssue.IdRedmine,
                Subject = atualExcelIssue.Subject,
                EstimatedHours = atualExcelIssue.EstimatedHours,
                StartDate = atualExcelIssue.StartDate,
                DueDate = atualExcelIssue.DueDate,
                AssignedTo = new IdentifiableName { Id = atualExcelIssue.AssigneeId },
                Tracker = new IdentifiableName { Id = atualExcelIssue.TrackerId },
                Project = new IdentifiableName { Id = atualExcelIssue.ProjectId },
                ParentIssue = atualExcelIssue.ParentExcelIssue != null && atualExcelIssue.ParentExcelIssue.IdRedmine != 0 ?
                    new IdentifiableName { Id = atualExcelIssue.ParentExcelIssue.IdRedmine } : null
            };

            if (atualizarProjetoExistente && atualExcelIssue.IdRedmine != 0)
            {
                try
                {
                    issueLoaded = manager.GetObject<Issue>(atualExcelIssue.IdRedmine.ToString(), null);
                    issueToSave = AtualizarSomenteModificacoes(issueLoaded, issueNew);
                }
                catch(RedmineException rex)
                {
                    Console.WriteLine("Mensagem de erro do sistema ao tentar carregar a Issue Id " + atualExcelIssue.IdRedmine.ToString() + ": " + rex.Message);
                    throw new Exception("O ID da Issue/Atividade sendo atualizada não foi encontrada no Redmine!");
                }
            }
            else
                issueToSave = issueNew;

            try
            {
                if (!atualizarProjetoExistente)
                {
                    issueToSave = manager.CreateObject(issueToSave);
                    atualExcelIssue.IdRedmine = issueToSave.Id;
                }
                else if (issueToSave.Id != 0)
                    manager.UpdateObject(issueToSave.Id.ToString(), issueToSave);
            }
            catch(RedmineException rex)
            {
                if (rex.Message.Contains("Tracker is not included in the list"))
                {
                    throw new Exception("Tracker Not Found");
                }
                else {
                    throw rex;
                }
            }

            return atualExcelIssue;
        }
        /**
         * <summary>Procura no Redmine pelo Tracker associado a tarefa (issue) e retorna seu ID</summary>
         * <returns>
         * O valor de retorno -1 (menos um) significa que o Tracker não foi atribuída a Issue.
         * Diferente do retorno 0 (zero) que significa que foi atribuida a Issue porém este não foi encontrado no Redmine.
         * Qualquer outro retorno representa o ID do Tracker no Redmine.
         * </returns>
        **/
        private int TrackerExiste(ExcelIssue excelIssue)
        {
            if (excelIssue.Tracker == null || excelIssue.Tracker == "")
                return -1;

            if (listaDeTrackers == null)
            {
                NameValueCollection parametros = new NameValueCollection();
                parametros.Add("project_id", excelIssue.ProjectId.ToString());
                listaDeTrackers = manager.GetObjectList<Tracker>(parametros);
            }

            List<Tracker> trackersFiltrados = listaDeTrackers.Where(x => x.Name == excelIssue.Tracker).ToList();

            if (trackersFiltrados.Count > 0)
                return trackersFiltrados[0].Id;
            else
                return 0;
        }
        /**
         * <summary>Procura no Redmine pelo usuário atribuido na tarefa (issue) e retorna seu ID</summary>
         * <returns>
         * O valor de retorno -1 (menos um) significa que a tarefa (issue) não foi atribuída a ninguem.
         * Diferente do retorno 0 (zero) que significa que foi atribuida a alguém porém este não foi encontrado no Redmine.
         * Qualquer outro retorno representa o ID do usuário no Redmine.
         * </returns>
        **/
        private int UsuarioExiste(ExcelIssue excelIssue)
        {
            if (excelIssue.AssigneeName == null)
                return -1;

            if (listaDeUsuarios == null)
            {
                var parametros = new NameValueCollection();
                parametros.Add("project_id", excelIssue.ProjectId.ToString());
                listaDeUsuarios = manager.GetObjectList<ProjectMembership>(parametros);
            }

            //User user = listaDeMembrosProjeto[1].User;

            List<ProjectMembership> usuariosFiltrados = listaDeUsuarios.Where(x => x.User.Name.Trim() == excelIssue.AssigneeName.Trim()).ToList();

            if (usuariosFiltrados.Count > 0)
                return usuariosFiltrados[0].User.Id;
            else
                return 0;
        }
        public static List<ExcelIssue> CarregarIssuesExcel(System.IO.Stream fileStream, int projectId)
        {
            List<ExcelIssue> IssueList = new List<ExcelIssue>();
            //2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
            IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fileStream);

            //3. DataSet - Create column names from first row
            excelReader.IsFirstRowAsColumnNames = true;
            DataSet result = excelReader.AsDataSet();

            bool sair = false;
            excelReader.Read(); //pula a primeira linha que contem o nome das colunas
            //4. Data Reader methods
            while (excelReader.Read() && !sair)
            {
                ExcelIssue issue = new ExcelIssue();

                try
                {
                    issue.OutlineNumber = excelReader.GetString(0);
                    issue.Subject = excelReader.GetString(1);
                    issue.EstimatedHours = excelReader.GetFloat(2);
                    issue.StartDate = excelReader.GetDateTime(3);
                    issue.DueDate = excelReader.GetDateTime(4);
                    issue.AssigneeName = excelReader.GetString(5);
                    issue.Tracker = excelReader.GetString(6);
                    issue.IdRedmine = excelReader.GetInt32(7) == -2147483648 ? 0 : excelReader.GetInt32(7);
                    issue.ProjectId = projectId;
                }
                catch (Exception ex)
                {
                    return null;
                }

                if (issue.OutlineNumber == "")
                    sair = true;
                else
                    IssueList.Add(issue);
            }

            //6. Free resources
            excelReader.Close();
            fileStream.Close();

            AssociarIssueFilhaAoPai(IssueList);

            return IssueList;
        }