def get_tasks_as_geojson_feature_collection_no_geom(project_id): """ Creates a geoJson.FeatureCollection object for all tasks related to the supplied project ID without geometry :param project_id: Owning project ID :return: geojson.FeatureCollection """ project_tasks = (db.session.query( Task.id, Task.x, Task.y, Task.zoom, Task.is_square, Task.task_status).filter(Task.project_id == project_id).all()) tasks_features = [] for task in project_tasks: task_properties = dict( taskId=task.id, taskX=task.x, taskY=task.y, taskZoom=task.zoom, taskIsSquare=task.is_square, taskStatus=TaskStatus(task.task_status).name, ) feature = geojson.Feature(properties=task_properties) tasks_features.append(feature) return geojson.FeatureCollection(tasks_features)
def get_last_activity(project_id: int) -> ProjectLastActivityDTO: """ Gets the last activity for a project's tasks """ results = (db.session.query( Task.id, Task.project_id, Task.task_status, Task.locked_by, Task.mapped_by, Task.validated_by, ).filter(Task.project_id == project_id).order_by(Task.id.asc())) last_activity_dto = ProjectLastActivityDTO() for item in results: latest = TaskStatusDTO() latest.task_id = item.id latest.task_status = TaskStatus(item.task_status).name latest_activity = (db.session.query( TaskHistory.action_date, TaskHistory.action, User.username).join(User).filter( TaskHistory.task_id == item.id, TaskHistory.project_id == project_id, TaskHistory.action != "COMMENT", User.id == TaskHistory.user_id, ).order_by(TaskHistory.id.desc()).first()) if latest_activity: latest.action_date = latest_activity[0] latest.action_by = latest_activity[2] last_activity_dto.activity.append(latest) return last_activity_dto
def get_last_activity(project_id: int) -> ProjectLastActivityDTO: """ Gets the last activity for a project's tasks """ sq = (TaskHistory.query.with_entities( TaskHistory.task_id, TaskHistory.action_date, TaskHistory.user_id, ).filter(TaskHistory.project_id == project_id).filter( TaskHistory.action != TaskAction.COMMENT.name).order_by( TaskHistory.task_id, TaskHistory.action_date.desc()).distinct( TaskHistory.task_id).subquery()) sq_statuses = (Task.query.with_entities( Task.id, Task.task_status).filter(Task.project_id == project_id).subquery()) results = (db.session.query( sq_statuses.c.id, sq.c.action_date, sq_statuses.c.task_status, User.username, ).outerjoin(sq, sq.c.task_id == sq_statuses.c.id).outerjoin( User, User.id == sq.c.user_id).order_by(sq_statuses.c.id).all()) dto = ProjectLastActivityDTO() dto.activity = [ TaskStatusDTO( dict( task_id=r.id, task_status=TaskStatus(r.task_status).name, action_date=r.action_date, action_by=r.username, )) for r in results ] return dto
def unlock_task(self, user_id, new_state=None, comment=None, undo=False, issues=None): """ Unlock task and ensure duration task locked is saved in History """ if comment: self.set_task_history( action=TaskAction.COMMENT, comment=comment, user_id=user_id, mapping_issues=issues, ) history = self.set_task_history( action=TaskAction.STATE_CHANGE, new_state=new_state, user_id=user_id, mapping_issues=issues, ) if (new_state in [TaskStatus.MAPPED, TaskStatus.BADIMAGERY] and TaskStatus( self.task_status) != TaskStatus.LOCKED_FOR_VALIDATION): # Don't set mapped if state being set back to mapped after validation self.mapped_by = user_id elif new_state == TaskStatus.VALIDATED: TaskInvalidationHistory.record_validation(self.project_id, self.id, user_id, history) self.validated_by = user_id elif new_state == TaskStatus.INVALIDATED: TaskInvalidationHistory.record_invalidation( self.project_id, self.id, user_id, history) self.mapped_by = None self.validated_by = None if not undo: # Using a slightly evil side effect of Actions and Statuses having the same name here :) TaskHistory.update_task_locked_with_duration( self.id, self.project_id, TaskStatus(self.task_status), user_id) self.task_status = new_state.value self.locked_by = None self.update()
def is_mappable(self): """ Determines if task in scope is in suitable state for mapping """ if TaskStatus(self.task_status) not in [ TaskStatus.READY, TaskStatus.INVALIDATED, ]: return False return True
def get_locked_tasks_for_user(user_id: int): """ Gets tasks on project owned by specified user id""" tasks = Task.query.filter_by(locked_by=user_id) tasks_dto = LockedTasksForUser() for task in tasks: tasks_dto.locked_tasks.append(task.id) tasks_dto.project = task.project_id tasks_dto.task_status = TaskStatus(task.task_status).name return tasks_dto
def reset_lock(self, user_id, comment=None): """ Removes a current lock from a task, resets to last status and updates history with duration of lock """ if comment: self.set_task_history(action=TaskAction.COMMENT, comment=comment, user_id=user_id) # Using a slightly evil side effect of Actions and Statuses having the same name here :) TaskHistory.update_task_locked_with_duration( self.id, self.project_id, TaskStatus(self.task_status), user_id) self.clear_lock()
def reset_task(self, user_id: int): if TaskStatus(self.task_status) in [ TaskStatus.LOCKED_FOR_MAPPING, TaskStatus.LOCKED_FOR_VALIDATION, ]: self.record_auto_unlock() self.set_task_history(TaskAction.STATE_CHANGE, user_id, None, TaskStatus.READY) self.mapped_by = None self.validated_by = None self.locked_by = None self.task_status = TaskStatus.READY.value self.update()
def as_dto( self, task_history: List[TaskHistoryDTO] = [], last_updated: datetime.datetime = None, ): """Just converts to a TaskDTO""" task_dto = TaskDTO() task_dto.task_id = self.id task_dto.project_id = self.project_id task_dto.task_status = TaskStatus(self.task_status).name task_dto.lock_holder = self.lock_holder.username if self.lock_holder else None task_dto.task_history = task_history task_dto.last_updated = last_updated if last_updated else None task_dto.auto_unlock_seconds = Task.auto_unlock_delta().total_seconds() return task_dto
def reset_task(self, user_id: int): expiry_delta = Task.auto_unlock_delta() lock_duration = (datetime.datetime.min + expiry_delta).time().isoformat() if TaskStatus(self.task_status) in [ TaskStatus.LOCKED_FOR_MAPPING, TaskStatus.LOCKED_FOR_VALIDATION, ]: self.record_auto_unlock(lock_duration) self.set_task_history(TaskAction.STATE_CHANGE, user_id, None, TaskStatus.READY) self.mapped_by = None self.validated_by = None self.locked_by = None self.task_status = TaskStatus.READY.value self.update()
def get_tasks_as_geojson_feature_collection( project_id, task_ids_str: str = None, order_by: str = None, order_by_type: str = "ASC", status: int = None, ): """ Creates a geoJson.FeatureCollection object for tasks related to the supplied project ID :param project_id: Owning project ID :order_by: sorting option: available values update_date and building_area_diff :status: task status id to filter by :return: geojson.FeatureCollection """ # subquery = ( # db.session.query(func.max(TaskHistory.action_date)) # .filter( # Task.id == TaskHistory.task_id, # Task.project_id == TaskHistory.project_id, # ) # .correlate(Task) # .group_by(Task.id) # .label("update_date") # ) query = db.session.query( Task.id, Task.x, Task.y, Task.zoom, Task.is_square, Task.task_status, Task.geometry.ST_AsGeoJSON().label("geojson"), Task.locked_by, # subquery, ) filters = [Task.project_id == project_id] if task_ids_str: task_ids = map(int, task_ids_str.split(",")) tasks = Task.get_tasks(project_id, task_ids) if not tasks or len(tasks) == 0: raise NotFound() else: tasks_filters = [task.id for task in tasks] filters = [ Task.project_id == project_id, Task.id.in_(tasks_filters) ] else: tasks = Task.get_all_tasks(project_id) if not tasks or len(tasks) == 0: raise NotFound() if status: filters.append(Task.task_status == status) if order_by == "effort_prediction": query = query.outerjoin(TaskAnnotation).filter(*filters) if order_by_type == "DESC": query = query.order_by( desc( cast( cast( TaskAnnotation. properties["building_area_diff"], Text), Float, ))) else: query = query.order_by( cast( cast(TaskAnnotation.properties["building_area_diff"], Text), Float, )) # elif order_by == "last_updated": # if order_by_type == "DESC": # query = query.filter(*filters).order_by(desc("update_date")) # else: # query = query.filter(*filters).order_by("update_date") else: query = query.filter(*filters) project_tasks = query.all() tasks_features = [] for task in project_tasks: task_geometry = geojson.loads(task.geojson) task_properties = dict( taskId=task.id, taskX=task.x, taskY=task.y, taskZoom=task.zoom, taskIsSquare=task.is_square, taskStatus=TaskStatus(task.task_status).name, lockedBy=task.locked_by, ) feature = geojson.Feature(geometry=task_geometry, properties=task_properties) tasks_features.append(feature) return geojson.FeatureCollection(tasks_features)