def test_edit_comment(self): self.generate_fixture_user_manager() self.generate_fixture_user_cg_artist() user = persons_service.get_person_raw(self.user["id"]) user_cg_artist = \ persons_service.get_person_raw(self.user_cg_artist["id"]) user_manager = \ persons_service.get_person_raw(self.user_manager["id"]) self.project.team = [self.person, user, user_cg_artist, user_manager] self.project.save() self.generate_fixture_task() path = "/actions/tasks/%s/comment/" % self.task.id data = { "task_status_id": self.wip_status_id, "comment": "comment test @John Doe" } comment = self.post(path, data) notifications = notifications_service.get_last_notifications("mention") self.assertEqual(len(notifications), 1) path = "/data/comments/%s" % comment["id"] data = {"text": "comment test @John Did2 @John Did3"} comment = self.put(path, data) notifications = notifications_service.get_last_notifications("mention") self.assertEqual(len(notifications), 2)
def test_comment_task(self): self.project_id = self.project.id self.generate_fixture_user_manager() self.generate_fixture_user_cg_artist() user_cg_artist = persons_service.get_person_raw( self.user_cg_artist["id"] ) user_manager = persons_service.get_person_raw(self.user_manager["id"]) self.project.team = [self.person, user_cg_artist, user_manager] self.project.save() self.generate_fixture_task() path = "/actions/tasks/%s/comment/" % self.task.id data = { "task_status_id": self.wip_status_id, "comment": "comment test", } comment = self.post(path, data) self.assertEqual(comment["text"], data["comment"]) self.assertEqual( comment["person"]["first_name"], self.user["first_name"] ) self.assertEqual(comment["task_status"]["short_name"], "wip") tasks = self.get("/data/tasks") self.assertEqual(len(tasks), 1) self.assertEqual(tasks[0]["task_status_id"], str(self.wip_status_id)) self.assertIsNotNone(tasks[0]["last_comment_date"]) comments = self.get("/data/comments/") self.assertEqual(len(comments), 1) self.assertEqual(comments[0]["text"], data["comment"]) self.assertEqual(comments[0]["person_id"], self.user["id"]) notifications = notifications_service.get_last_notifications("comment") self.assertEqual(len(notifications), 1) notifications = notifications_service.get_last_notifications("mention") self.assertEqual(len(notifications), 0) data = { "task_status_id": self.wip_status_id, "comment": "comment test @John Did2", } comment = self.post(path, data) notifications = notifications_service.get_last_notifications("comment") self.assertEqual(len(notifications), 2) notifications = notifications_service.get_last_notifications("mention") self.assertEqual(len(notifications), 1) news_list = news_service.get_last_news_for_project(self.project_id) self.assertEqual(len(news_list["data"]), 2)
def send_assignation_notification(person_id, author_id, task): """ Send a notification email telling that somenone assigned to a task the person matching given person id. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled or person.notifications_slack_enabled: (author, task_name, task_url) = get_task_descriptors(author_id, task) subject = "[Kitsu] You were assigned to %s" % task_name email_message = """<p><strong>%s</strong> assigned you to <a href="%s">%s</a>.</p> """ % ( author["full_name"], task_url, task_name, ) slack_message = """*%s* assigned you to <%s|%s>. """ % ( author["full_name"], task_url, task_name, ) messages = { "email_message": email_message, "slack_message": slack_message, } return send_notification(person_id, subject, messages) return True
def pre_update(self, instance_dict, data): if "assignees" in data: data["assignees"] = [ persons_service.get_person_raw(assignee) for assignee in data["assignees"] ] return data
def send_notification(person_id, subject, messages): """ Send email notification to given person. Use the job queue if it is activated. """ person = persons_service.get_person_raw(person_id) email_message = messages["email_message"] slack_message = messages["slack_message"] if person.notifications_enabled: if config.ENABLE_JOB_QUEUE: queue_store.job_queue.enqueue( emails.send_email, args=(subject, email_message + get_signature(), person.email), ) else: emails.send_email(subject, email_message + get_signature(), person.email) if person.notifications_slack_enabled: organisation = persons_service.get_organisation() userid = person.notifications_slack_userid token = organisation.get("chat_token_slack", "") if config.ENABLE_JOB_QUEUE: queue_store.job_queue.enqueue(chats.send_to_slack, args=(token, userid, slack_message)) else: chats.send_to_slack(token, userid, slack_message) return True
def get_raw_quota_shots_between(person_id, start, end, project_id=None, task_type_id=None): """ Get all shots leading to a quota computation during the given period. """ shot_type = get_shot_type() person = persons_service.get_person_raw(person_id) shots = [] query = (Entity.query.filter( Entity.entity_type_id == shot_type["id"]).filter( Task.project_id == project_id).filter( Task.task_type_id == task_type_id).filter( Task.end_date.between(start, end)).filter( Task.assignees.contains(person)).join( Task, Entity.id == Task.entity_id).join( Project, Project.id == Task.project_id)) query_shots = query.all() for entity in query_shots: shot = entity.serialize() full_name, _ = names_service.get_full_entity_name(shot["id"]) shot["full_name"] = full_name shot["weight"] = 1 shots.append(shot) return sorted(shots, key=itemgetter("full_name"))
def send_comment_notification(person_id, author_id, comment, task): """ Send a notification emali telling that a new comment was posted to person matching given person id. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled: task_status = tasks_service.get_task_status(task["task_status_id"]) (author, task_name, task_url) = get_task_descriptors(author_id, task) subject = "[Kitsu] %s - %s commented on %s" % ( task_status["short_name"], author["first_name"], task_name ) message = """%s wrote a comment on %s and changed the status to %s: "%s" To reply connect to this URL: %s %s """ % ( author["full_name"], task_name, task_status["short_name"], comment["text"], task_url, get_signature() ) return send_notification(person_id, subject, message) else: return True
def send_mention_notification(person_id, author_id, comment, task): """ Send a notification email telling that somenone mentioned the person matching given person id. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled: (author, task_name, task_url) = get_task_descriptors(author_id, task) subject = "[Kitsu] %s mentioned you on %s" % ( author["first_name"], task_name ) message = """%s mentioned you in a comment on %s: "%s" To reply connect to this URL: %s %s """ % ( author["full_name"], task_name, comment["text"], task_url, get_signature() ) return send_notification(person_id, subject, message) else: return True
def pre_update(self, project_dict, data): if "team" in data: data["team"] = [ persons_service.get_person_raw(person_id) for person_id in data["team"] ] if "asset_types" in data: data["asset_types"] = [ assets_service.get_asset_type_raw(asset_type_id) for asset_type_id in data["asset_types"] ] if "task_statuses" in data: data["task_statuses"] = [ tasks_service.get_task_status_raw(task_status_id) for task_status_id in data["task_statuses"] ] if "task_types" in data: data["task_types"] = [ tasks_service.get_task_type_raw(task_type_id) for task_type_id in data["task_types"] ] if "status_automations" in data: data["status_automations"] = [ status_automations_service.get_status_automation_raw( task_type_id) for task_type_id in data["status_automations"] ] return data
def update_data(self, data): open_status = projects_service.get_or_create_open_status() if "project_status_id" not in data: data["project_status_id"] = open_status["id"] if "team" in data: data["team"] = [ persons_service.get_person_raw(person_id) for person_id in data["team"] ] if "asset_types" in data: data["asset_types"] = [ assets_service.get_asset_type_raw(asset_type_id) for asset_type_id in data["asset_types"] ] if "task_statuses" in data: data["task_statuses"] = [ tasks_service.get_task_status_raw(task_status_id) for task_status_id in data["task_statuses"] ] if "task_types" in data: data["task_types"] = [ tasks_service.get_task_type_raw(task_type_id) for task_type_id in data["task_types"] ] if "status_automations" in data: data["status_automations"] = [ status_automations_service.get_status_automation_raw( task_type_id) for task_type_id in data["status_automations"] ] return data
def send_comment_notification(person_id, author_id, comment, task): """ Send a notification emali telling that a new comment was posted to person matching given person id. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled or person.notifications_slack_enabled: task_status = tasks_service.get_task_status(task["task_status_id"]) (author, task_name, task_url) = get_task_descriptors(author_id, task) subject = "[Kitsu] %s - %s commented on %s" % ( task_status["short_name"], author["first_name"], task_name, ) if len(comment["text"]) > 0: email_message = """<p><strong>%s</strong> wrote a comment on <a href="%s">%s</a> and set the status to <strong>%s</strong>.</p> <p><em>%s</em></p> """ % ( author["full_name"], task_url, task_name, task_status["short_name"], comment["text"], ) slack_message = """*%s* wrote a comment on <%s|%s> and set the status to *%s*. _%s_ """ % ( author["full_name"], task_url, task_name, task_status["short_name"], comment["text"], ) else: email_message = """<p><strong>%s</strong> changed status of <a href="%s">%s</a> to <strong>%s</strong>.</p> """ % ( author["full_name"], task_url, task_name, task_status["short_name"], ) slack_message = """*%s* changed status of <%s|%s> to *%s*. """ % ( author["full_name"], task_url, task_name, task_status["short_name"], ) messages = { "email_message": email_message, "slack_message": slack_message, } send_notification(person_id, subject, messages) return True
def post_update(self, instance_dict): persons_service.clear_person_cache() index_service.remove_person_index(instance_dict["id"]) person = persons_service.get_person_raw(instance_dict["id"]) if person.active: index_service.index_person(person) instance_dict["departments"] = [ str(department.id) for department in self.instance.departments ] return instance_dict
def assign_task(task_id, person_id): task = get_task_raw(task_id) person = persons_service.get_person_raw(person_id) task.assignees.append(person) task.save() task_dict = task.serialize() events.emit("task:assign", { "task": task_dict, "person": person.serialize() }) return task_dict
def assign_task(task_id, person_id): """ Assign given person to given task. Emit a *task:assign* event. """ task = get_task_raw(task_id) person = persons_service.get_person_raw(person_id) task.assignees.append(person) task.save() task_dict = task.serialize() events.emit("task:assign", {"task_id": task.id, "person_id": person.id}) return task_dict
def send_notification(person_id, subject, message): """ Send email notification to given person. Use the job queue if it is activated. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled: if config.ENABLE_JOB_QUEUE: queue_store.job_queue.enqueue( emails.send_email, args=(subject, message, person.email) ) else: emails.send_email(subject, message, person.email) return True
def assign_task(task_id, person_id): """ Assign given person to given task. Emit a *task:assign* event. """ task = get_task_raw(task_id) project_id = str(task.project_id) person = persons_service.get_person_raw(person_id) task.assignees.append(person) task.save() task_dict = task.serialize() events.emit("task:assign", { "task_id": task.id, "person_id": person.id }, project_id=project_id) clear_task_cache(task_id) events.emit("task:update", {"task_id": task_id}, project_id=project_id) return task_dict
def send_assignation_notification(person_id, author_id, task): """ Send a notification email telling that somenone assigned to a task the person matching given person id. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled: (author, task_name, task_url) = get_task_descriptors(author_id, task) subject = "[Kitsu] You were assigned to %s" % task_name message = """ %s assigned you to %s. To see the task details connect to this URL: %s %s """ % ( author["full_name"], task_name, task_url, get_signature() ) return send_notification(person_id, subject, message) return True
def send_mention_notification(person_id, author_id, comment, task): """ Send a notification email telling that somenone mentioned the person matching given person id. """ person = persons_service.get_person_raw(person_id) if person.notifications_enabled or person.notifications_slack_enabled: (author, task_name, task_url) = get_task_descriptors(author_id, task) subject = "[Kitsu] %s mentioned you on %s" % ( author["first_name"], task_name, ) email_message = """<p><strong>%s</strong> mentioned you in a comment on <a href="%s">%s</a>:</p> <p><em>%s</em></p> """ % ( author["full_name"], task_url, task_name, comment["text"], ) slack_message = """*%s* mentioned you in a comment on <%s|%s>. _%s_ """ % ( author["full_name"], task_url, task_name, comment["text"], ) messages = { "email_message": email_message, "slack_message": slack_message, } return send_notification(person_id, subject, messages) else: return True
def get_weighted_quota_shots_between(person_id, start, end, project_id=None, task_type_id=None): """ Get all shots leading to a quota computation during the given period. Set a weight on each one: * If there is time spent filled, weight it by the sum of duration divided py the overall task duration. * If there is no time spent, weight it by the number of business days in the time interval spent between WIP date (start) and feedback date (end). """ shot_type = get_shot_type() person = persons_service.get_person_raw(person_id) shots = [] already_listed = {} query = (Entity.query.filter( Entity.entity_type_id == shot_type["id"]).filter( Task.project_id == project_id).filter( Task.task_type_id == task_type_id).filter( Task.end_date != None).filter( TimeSpent.person_id == person_id). filter(TimeSpent.date >= start).filter(TimeSpent.date < end).join( Task, Entity.id == Task.entity_id).join( Project, Project.id == Task.project_id).join( TimeSpent, Task.id == TimeSpent.task_id).add_columns( Task.duration, TimeSpent.duration)) query_shots = query.all() for (entity, task_duration, duration) in query_shots: shot = entity.serialize() if shot["id"] not in already_listed: full_name, _ = names_service.get_full_entity_name(shot["id"]) shot["full_name"] = full_name shot["weight"] = round(duration / task_duration, 2) or 0 shots.append(shot) already_listed[shot["id"]] = shot else: shot = already_listed[shot["id"]] shot["weight"] += round(duration / task_duration, 2) start = date_helpers.get_datetime_from_string(start) end = date_helpers.get_datetime_from_string(end) query = (Entity.query.filter( Entity.entity_type_id == shot_type["id"]).filter( Task.project_id == project_id).filter( Task.task_type_id == task_type_id).filter( Task.end_date != None).filter( Task.real_start_date != None).filter( Task.assignees.contains(person)). filter((Task.real_start_date <= end) & (Task.end_date >= start)).filter( TimeSpent.id == None).join( Task, Entity.id == Task.entity_id).join( Project, Project.id == Task.project_id).outerjoin( TimeSpent, TimeSpent.task_id == Task.id).add_columns( Task.real_start_date, Task.end_date)) query_shots = query.all() for (entity, task_start, task_end) in query_shots: shot = entity.serialize() if shot["id"] not in already_listed: business_days = ( date_helpers.get_business_days(task_start, task_end) + 1) full_name, _ = names_service.get_full_entity_name(shot["id"]) shot["full_name"] = full_name multiplicator = 1 if task_start >= start and task_end <= end: multiplicator = business_days elif task_start >= start: multiplicator = ( date_helpers.get_business_days(task_start, end) + 1) elif task_end <= end: multiplicator = ( date_helpers.get_business_days(start, task_end) + 1) shot["weight"] = round(multiplicator / business_days, 2) already_listed[shot["id"]] = True shots.append(shot) return sorted(shots, key=itemgetter("full_name"))