diff --git a/vms/hooks.py b/vms/hooks.py index ea91d8c..860cdce 100644 --- a/vms/hooks.py +++ b/vms/hooks.py @@ -135,13 +135,11 @@ # --------------- # Hook on document methods and events -# doc_events = { -# "*": { -# "on_update": "method", -# "on_cancel": "method", -# "on_trash": "method" -# } -# } +doc_events = { + "VMS Review Comment": { + "after_insert": "vms.notifications.send_comment_notification", + }, +} # Scheduled Tasks # --------------- diff --git a/vms/notifications.py b/vms/notifications.py new file mode 100644 index 0000000..bbe3428 --- /dev/null +++ b/vms/notifications.py @@ -0,0 +1,86 @@ +import frappe +from frappe import _ + + +def send_comment_notification(doc, method): + """Send email notification when a new review comment is added. + + - Notify the asset uploader when someone else comments on their upload. + - Notify the parent comment author when someone replies to their comment. + """ + frappe.enqueue( + _send_comment_email, + queue="short", + comment_name=doc.name, + now=frappe.flags.in_test, + ) + + +def _send_comment_email(comment_name): + comment = frappe.get_doc("VMS Review Comment", comment_name) + asset = frappe.get_doc("VMS Asset", comment.asset) + + commenter_name = _get_commenter_display_name(comment) + asset_url = _get_review_url(asset) + + recipients = set() + + # 1. Notify the uploader (if someone else commented) + if asset.uploaded_by and asset.uploaded_by != comment.commented_by: + recipients.add(asset.uploaded_by) + + # 2. Notify parent comment author (if this is a reply) + if comment.parent_comment: + parent = frappe.get_doc("VMS Review Comment", comment.parent_comment) + if parent.commented_by and parent.commented_by != comment.commented_by: + recipients.add(parent.commented_by) + + if not recipients: + return + + subject = _("{0} commented on {1}").format(commenter_name, asset.file_name) + timestamp_str = "" + if comment.video_timestamp is not None and comment.video_timestamp > 0: + timestamp_str = f" at {_format_timestamp(comment.video_timestamp)}" + + is_reply = bool(comment.parent_comment) + action_text = _("replied to a comment") if is_reply else _("left a comment") + + message = f""" +

{commenter_name} {action_text} on {asset.file_name}{timestamp_str}:

+
+{frappe.utils.escape_html(comment.comment_text)} +
+

View in Review

+""" + + try: + frappe.sendmail( + recipients=list(recipients), + subject=subject, + message=message, + reference_doctype="VMS Review Comment", + reference_name=comment.name, + now=True, + ) + except Exception: + frappe.log_error(title=_("VMS: Failed to send comment notification")) + + +def _get_commenter_display_name(comment): + if comment.guest_name: + return f"{comment.guest_name} (Guest)" + if comment.commented_by: + return frappe.db.get_value("User", comment.commented_by, "full_name") or comment.commented_by + return _("Someone") + + +def _get_review_url(asset): + site_url = frappe.utils.get_url() + return f"{site_url}/vms/review/{asset.name}" + + +def _format_timestamp(seconds): + mins = int(seconds) // 60 + secs = int(seconds) % 60 + return f"{mins}:{secs:02d}"