Esempio n. 1
0
        private async Task <string> MoveMembersToProjectAsync(string messageString)
        {
            Console.WriteLine("Prepare members stage started");
            MoveTaskMoveMembersMessage message = JsonConvert.DeserializeObject <MoveTaskMoveMembersMessage>(messageString);

            string transactionId = message.TransactionId;
            var    transaction   = await _transactionsRepository.GetTransactionAsync(transactionId);

            if (transaction != null && transaction.State == TransactionStates.Denied)
            {
                return($"Transaction {transactionId} already denied");
            }

            IEnumerable <string> taskMembers = message.TaskMembers;

            var moveTransaction = transaction == null
                ? MoveTaskTransaction.Create(transactionId, message.TargetProjectId)
                : MoveTaskTransaction.CreateFromBase(transaction);

            moveTransaction.State = TransactionStates.Processing;

            if (taskMembers.IsNullOrEmpty())
            {
                // nothing to move
                await HandleNoMembersToMoveAsync(moveTransaction);

                return($"No task members to move");
            }

            //Check project
            string projectId = message.TargetProjectId;
            var    project   = await _projectsRepository.GetProjectAsync(projectId);

            if (project == null)
            {
                string reason = $"Project {projectId} not found";

                var rollbackOutboxMessage = OutboxMessageModel.Create(
                    new RollbackTransactionMessage
                {
                    TransactionId = transactionId,
                    Reason        = reason
                }, Topics.ProjectMembers, TransactionMessageActions.MoveTask_Rollback);

                moveTransaction.State   = TransactionStates.Denied;
                moveTransaction.Message = reason;
                moveTransaction.UpdateData();

                await _transactionsRepository.CreateOrUpdateTransactionAsync(moveTransaction, rollbackOutboxMessage);

                return(reason);
            }


            var targetProjectMembers = await _projectMembersRepository.GetProjectsMembersAsync(projectId : projectId);

            var targetMembersIds = targetProjectMembers?.Select(m => m.UserId).ToList() ?? new List <string>();
            var movingMembersIds = taskMembers.Except(targetMembersIds).ToList();

            if (!movingMembersIds.Any())
            {
                await HandleNoMembersToMoveAsync(moveTransaction);

                return($"All members already in target");
            }

            var allUsersById = (await _usersRepository.GetAllUsersAsync()).ToDictionary(u => u.Id);
            var allUsersIds  = allUsersById.Keys.ToList();

            var notFoundMembers = movingMembersIds.Except(allUsersIds).ToList();

            // Check all members exists
            if (notFoundMembers.Any())
            {
                string reason = $"Members {string.Join(", ", notFoundMembers)} not found";

                var rollbackOutboxMessage = OutboxMessageModel.Create(
                    new RollbackTransactionMessage
                {
                    TransactionId = transactionId,
                    Reason        = reason
                }, Topics.ProjectMembers, TransactionMessageActions.MoveTask_Rollback);

                moveTransaction.State   = TransactionStates.Denied;
                moveTransaction.Message = reason;
                moveTransaction.UpdateData();

                await _transactionsRepository.CreateOrUpdateTransactionAsync(moveTransaction, rollbackOutboxMessage);

                return(reason);
            }

            var sourceProjectMembersById = (await _projectMembersRepository.GetProjectsMembersAsync(projectId: message.SourceProjectId))
                                           .ToDictionary(m => m.UserId);


            //probably will be better rollback this insterts in case of exception
            foreach (var movingMemberId in movingMembersIds)
            {
                ProjectMemberRole role = ProjectMemberRole.Implementer;

                //try use role from source project
                if (sourceProjectMembersById.TryGetValue(movingMemberId, out var sourceProjectMember))
                {
                    role = sourceProjectMember.Role;
                }

                var projectMemberModel = new ProjectMemberModel
                {
                    UserId    = movingMemberId,
                    ProjectId = projectId,
                    Role      = role
                };

                var outboxMessage = OutboxMessageModel.Create(
                    new ProjectMemberCreatedUpdatedMessage
                {
                    Role         = role,
                    UserId       = movingMemberId,
                    Username     = allUsersById[movingMemberId].Username,
                    ProjectId    = projectId,
                    ProjectTitle = project.Title
                }, Topics.ProjectMembers, MessageActions.Created);

                await _projectMembersRepository.AddMemberToProjectAsync(projectMemberModel, outboxMessage);
            }

            moveTransaction.MovedMembers = movingMembersIds.ToList();
            moveTransaction.UpdateData();

            var movedOutboxMessage = OutboxMessageModel.Create(
                new MoveTaskMembersMovedMessage
            {
                TransactionId = transactionId,
            }, Topics.ProjectMembers, TransactionMessageActions.MoveTask_MoveMembersCompleted);

            await _transactionsRepository.CreateOrUpdateTransactionAsync(moveTransaction, movedOutboxMessage);

            return($"Moving task members completed successful");
        }
 ///
 /// All projects of the member or all members of the project
 ///
 public Task <IEnumerable <ProjectMemberAggregate> > GetProjectsMembersAsync(string projectId = null, string userId = null)
 {
     return(_projectMembersRepository.GetProjectsMembersAsync(projectId, userId));
 }