def undo_mapping(project_id: int, task_id: int, user_id: int, preferred_locale: str = "en") -> TaskDTO: """ Allows a user to Undo the task state they updated """ task = MappingService.get_task(task_id, project_id) if not MappingService._is_task_undoable(user_id, task): raise MappingServiceError("Undo not allowed for this user") current_state = TaskStatus(task.task_status) undo_state = TaskHistory.get_last_status(project_id, task_id, True) # Refer to last action for user of it. last_action = TaskHistory.get_last_action(project_id, task_id) StatsService.update_stats_after_task_state_change( project_id, last_action.user_id, current_state, undo_state, "undo") task.unlock_task( user_id, undo_state, f"Undo state from {current_state.name} to {undo_state.name}", True, ) return task.as_dto_with_instructions(preferred_locale)
def unlock_task_after_mapping(mapped_task: MappedTaskDTO) -> TaskDTO: """ Unlocks the task and sets the task history appropriately """ task = MappingService.get_task_locked_by_user(mapped_task.project_id, mapped_task.task_id, mapped_task.user_id) new_state = TaskStatus[mapped_task.status.upper()] if new_state not in [ TaskStatus.MAPPED, TaskStatus.BADIMAGERY, TaskStatus.READY, ]: raise MappingServiceError( "Can only set status to MAPPED, BADIMAGERY, READY after mapping" ) # Update stats around the change of state last_state = TaskHistory.get_last_status(mapped_task.project_id, mapped_task.task_id, True) StatsService.update_stats_after_task_state_change( mapped_task.project_id, mapped_task.user_id, last_state, new_state) if mapped_task.comment: # Parses comment to see if any users have been @'d MessageService.send_message_after_comment( mapped_task.user_id, mapped_task.comment, task.id, mapped_task.project_id, ) task.unlock_task(mapped_task.user_id, new_state, mapped_task.comment) return task.as_dto_with_instructions(mapped_task.preferred_locale)
def get_all_comments(project_id: int) -> ProjectCommentsDTO: """ Gets all comments mappers, validators have added to tasks associated with project """ comments = TaskHistory.get_all_comments(project_id) if len(comments.comments) == 0: raise NotFound("No comments found on project") return comments
def test_task_is_not_undoable_if_last_change_not_made_by_you( self, last_action, mock_project): # Arrange task_history = TaskHistory(1, 1, 1) task_history.user_id = 2 last_action.return_value = task_history task = Task() task.task_status = TaskStatus.MAPPED.value task.mapped_by = 1 # Act mock_project.return_value = False is_undoable = MappingService._is_task_undoable(1, task) # Assert self.assertFalse(is_undoable)
def _is_task_undoable(logged_in_user_id: int, task: Task) -> bool: """ Determines if the current task status can be undone by the logged in user """ # Test to see if user can undo status on this task if logged_in_user_id and TaskStatus(task.task_status) not in [ TaskStatus.LOCKED_FOR_MAPPING, TaskStatus.LOCKED_FOR_VALIDATION, TaskStatus.READY, ]: last_action = TaskHistory.get_last_action(task.project_id, task.id) # User requesting task made the last change, so they are allowed to undo it. if last_action.user_id == int( logged_in_user_id ) or ProjectService.is_user_permitted_to_validate( task.project_id, logged_in_user_id): return True return False
def unlock_tasks_after_validation( validated_dto: UnlockAfterValidationDTO, ) -> TaskDTOs: """ Unlocks supplied tasks after validation :raises ValidatorServiceError """ validated_tasks = validated_dto.validated_tasks project_id = validated_dto.project_id user_id = validated_dto.user_id tasks_to_unlock = ValidatorService.get_tasks_locked_by_user( project_id, validated_tasks, user_id) # Unlock all tasks dtos = [] message_sent_to = [] for task_to_unlock in tasks_to_unlock: task = task_to_unlock["task"] if task_to_unlock["comment"]: # Parses comment to see if any users have been @'d MessageService.send_message_after_comment( validated_dto.user_id, task_to_unlock["comment"], task.id, validated_dto.project_id, ) if (task_to_unlock["new_state"] == TaskStatus.VALIDATED or task_to_unlock["new_state"] == TaskStatus.INVALIDATED): # All mappers get a notification if their task has been validated or invalidated. # Only once if multiple tasks mapped if task.mapped_by not in message_sent_to: MessageService.send_message_after_validation( task_to_unlock["new_state"], validated_dto.user_id, task.mapped_by, task.id, validated_dto.project_id, ) message_sent_to.append(task.mapped_by) if task_to_unlock["new_state"] == TaskStatus.VALIDATED: # Set last_validation_date for the mapper to current date task.mapper.last_validation_date = timestamp() # Update stats if user setting task to a different state from previous state prev_status = TaskHistory.get_last_status(project_id, task.id) if prev_status != task_to_unlock["new_state"]: StatsService.update_stats_after_task_state_change( validated_dto.project_id, validated_dto.user_id, prev_status, task_to_unlock["new_state"], ) task_mapping_issues = ValidatorService.get_task_mapping_issues( task_to_unlock) task.unlock_task( validated_dto.user_id, task_to_unlock["new_state"], task_to_unlock["comment"], issues=task_mapping_issues, ) dtos.append( task.as_dto_with_instructions(validated_dto.preferred_locale)) task_dtos = TaskDTOs() task_dtos.tasks = dtos return task_dtos