public async Task UpdateProjectMebmerRoleAsync(ProjectMemberModel updatingMember)
        {
            ProjectMemberModel currentMember = await _projectMembersRepository
                                               .GetProjectMemberAsync(updatingMember.ProjectId, updatingMember.UserId);

            if (currentMember == null)
            {
                throw new NotFoundException($"User with id = {updatingMember.UserId} not found in project with id {updatingMember.ProjectId}");
            }

            (string projectTitle, string username) = await EnsureProjectAndUserExistAsync(updatingMember.ProjectId, updatingMember.UserId);

            var outboxMessage = OutboxMessageModel.Create(
                new ProjectMemberCreatedUpdatedMessage
            {
                ProjectId    = updatingMember.ProjectId,
                ProjectTitle = projectTitle,
                UserId       = updatingMember.UserId,
                Username     = username,
                Role         = updatingMember.Role
            }, Topics.ProjectMembers, MessageActions.Updated
                );

            await _projectMembersRepository.UpdateProjectMemberAsync(updatingMember, outboxMessage);
        }
        public async Task AddMemberToProjectAsync(ProjectMemberModel newProjectMember, OutboxMessageModel outboxMessage)
        {
            string insertQuery = $"insert into {_tableName} (userid, projectid, role) "
                                 + $"values('{newProjectMember.UserId}', '{newProjectMember.ProjectId}', '{(int)newProjectMember.Role}');";

            string insertOutboxMessageQuery = ConstructInsertMessageQuery(outboxMessage);

            insertQuery += insertOutboxMessageQuery;

            int res = await _connection.ExecuteAsync(insertQuery);

            if (res <= 0)
            {
                throw new DatabaseException("Add member to project failed");
            }
        }
        public async Task UpdateProjectMemberAsync(ProjectMemberModel updatingProjectMember, OutboxMessageModel outboxMessage)
        {
            string updateQuery = $"update {_tableName} set " +
                                 $"role = '{(int)updatingProjectMember.Role}' " +
                                 $"where userid = '{updatingProjectMember.UserId}' and projectId = '{updatingProjectMember.ProjectId}';";

            string insertOutboxMessageQuery = ConstructInsertMessageQuery(outboxMessage);

            updateQuery += insertOutboxMessageQuery;

            int res = await _connection.ExecuteAsync(updateQuery);

            if (res <= 0)
            {
                throw new DatabaseException("Update project member failed");
            }
        }
        public async Task AddMemberToProjectAsync(ProjectMemberModel newProjectMember, string requestId)
        {
            if (!(await CheckAndSaveRequestIdAsync(requestId)))
            {
                throw new AlreadyHandledException();
            }

            (string projectTitle, string username) = await EnsureProjectAndUserExistAsync(newProjectMember.ProjectId, newProjectMember.UserId);

            try
            {
                var existingMember = await _projectMembersRepository.GetProjectMemberAsync(newProjectMember.ProjectId, newProjectMember.UserId);

                if (existingMember != null)
                {
                    throw new EntityExistsException("This member already in project");
                }

                var outboxMessage = OutboxMessageModel.Create(
                    new ProjectMemberCreatedUpdatedMessage
                {
                    ProjectId    = newProjectMember.ProjectId,
                    ProjectTitle = projectTitle,
                    UserId       = newProjectMember.UserId,
                    Username     = username,
                    Role         = newProjectMember.Role
                }, Topics.ProjectMembers, MessageActions.Created
                    );

                await _projectMembersRepository.AddMemberToProjectAsync(newProjectMember, outboxMessage);
            }
            catch (Exception)
            {
                //rollback request id
                await _requestsRepository.DeleteRequestIdAsync(requestId);

                throw;
            }
        }
Esempio n. 5
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");
        }