import frappe # Supersedes create_resolution_notifications.py and create_workflow_step_notifications.py: # same idea, but event='Value Change' + a `doc.workflow_state == "..."` condition per # state (matching the "Idea Is in Accept & Under Progress" example), one record per # *state* rather than per action — several actions land on the same state (e.g. Process's # "Submit for Review" and "Start New Cycle" both end in Pending Actor), so this is also # fewer records than the per-action version. sidrah_business.api._fire_alert() still # calls `.send(doc)` explicitly right after workflow_state is set (event='Value Change' # alone won't auto-fire here — workflow_state moves via frappe.db.set_value to dodge # Frappe's own Workflow permission check, so Frappe's own auto-dispatch never sees it # change) — the condition on each record is honored by _fire_alert before it sends, so # editing a condition in Desk still changes real behavior. _SENDER_ACCOUNT = 'Asset Notifications' _OLD_NAMES = [ 'SB Incident Resolved', 'SB Idea Resolved', 'SB Order Closed', 'SB Process - Submit for Review', 'SB Process - Update Status', 'SB Process - Add Comment', 'SB Process - Move to Study', 'SB Process - Start New Cycle', 'SB Order - Submit for Review', 'SB Order - Update Status', 'SB Order - Move to Study', 'SB Order - Start New Cycle', 'SB Incident - Submit', 'SB Incident - Assign to Manager', 'SB Incident - Reject', 'SB Idea - Submit', 'SB Idea - Assign to Manager', 'SB Idea - Reject', 'SB Idea - Submit Proposal', ] _ALERTS = [ # ── SB Idea ────────────────────────────────────────────────────────────── { 'name': 'SB Idea - Initial Evaluation', 'document_type': 'SB Idea', 'state': 'Initial Evaluation', 'subject': '{{ doc.name }} Idea Is in Initial Evaluation. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}], }, { 'name': 'SB Idea - Accept & Under Progress', 'document_type': 'SB Idea', 'state': 'Accept & Under Progress', 'subject': '{{ doc.name }} Idea Is in Accept & Under Progress. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'assigned_to'}], }, { 'name': 'SB Idea - working on proposal', 'document_type': 'SB Idea', 'state': 'working on proposal', 'subject': '{{ doc.name }} Idea Is in working on proposal. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}], }, { 'name': 'SB Idea - Executed & Closed', 'document_type': 'SB Idea', 'state': 'Executed & Closed', 'subject': '{{ doc.name }} Idea Is in Executed & Closed. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'owner'}], }, { 'name': 'SB Idea - Rejected', 'document_type': 'SB Idea', 'state': 'Rejected', 'subject': '{{ doc.name }} Idea Is in Rejected. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'owner'}], }, # ── SB Incident ────────────────────────────────────────────────────────── { 'name': 'SB Incident - Initial Evaluation', 'document_type': 'SB Incident', 'state': 'Initial Evaluation', 'subject': '{{ doc.name }} Incident Is in Initial Evaluation. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}], }, { 'name': 'SB Incident - Accept & Under Progress', 'document_type': 'SB Incident', 'state': 'Accept & Under Progress', 'subject': '{{ doc.name }} Incident Is in Accept & Under Progress. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'assigned_to'}], }, { 'name': 'SB Incident - Executed & Closed', 'document_type': 'SB Incident', 'state': 'Executed & Closed', 'subject': '{{ doc.name }} Incident Is in Executed & Closed. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'owner'}], }, { 'name': 'SB Incident - Rejected', 'document_type': 'SB Incident', 'state': 'Rejected', 'subject': '{{ doc.name }} Incident Is in Rejected. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'owner'}], }, # ── SB Process ─────────────────────────────────────────────────────────── { 'name': 'SB Process - Pending Actor', 'document_type': 'SB Process', 'state': 'Pending Actor', 'subject': '{{ doc.name }} Process Is in Pending Actor. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'actor'}], }, { 'name': 'SB Process - Pending Comment', 'document_type': 'SB Process', 'state': 'Pending Comment', 'subject': '{{ doc.name }} Process Is in Pending Comment. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}, {'receiver_by_role': 'SB Manager'}], }, { 'name': 'SB Process - Review', 'document_type': 'SB Process', 'state': 'Review', 'subject': '{{ doc.name }} Process Is in Review. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}, {'receiver_by_role': 'SB Manager'}], }, { 'name': 'SB Process - In Study', 'document_type': 'SB Process', 'state': 'In Study', 'subject': '{{ doc.name }} Process Is in In Study. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}, {'receiver_by_role': 'SB Manager'}], }, # ── SB Order ───────────────────────────────────────────────────────────── { 'name': 'SB Order - Pending Actor', 'document_type': 'SB Order', 'state': 'Pending Actor', 'subject': '{{ doc.name }} Order Is in Pending Actor. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'actor'}], }, { 'name': 'SB Order - Review', 'document_type': 'SB Order', 'state': 'Review', 'subject': '{{ doc.name }} Order Is in Review. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}, {'receiver_by_role': 'SB Manager'}, {'receiver_by_role': 'SB Owner'}], }, { 'name': 'SB Order - In Study', 'document_type': 'SB Order', 'state': 'In Study', 'subject': '{{ doc.name }} Order Is in In Study. Take Necessary Action', 'recipients': [{'receiver_by_role': 'SB Auditor'}, {'receiver_by_role': 'SB Manager'}, {'receiver_by_role': 'SB Owner'}], }, { 'name': 'SB Order - Closed', 'document_type': 'SB Order', 'state': 'Closed', 'subject': '{{ doc.name }} Order Is in Closed. Take Necessary Action', 'recipients': [{'receiver_by_document_field': 'owner'}], }, ] def execute(): for old_name in _OLD_NAMES: if frappe.db.exists('Notification', old_name): frappe.delete_doc('Notification', old_name, ignore_permissions=True, force=True) if not frappe.db.exists('Email Account', _SENDER_ACCOUNT): frappe.db.commit() return for spec in _ALERTS: if frappe.db.exists('Notification', spec['name']): frappe.delete_doc('Notification', spec['name'], ignore_permissions=True, force=True) frappe.get_doc({ 'doctype': 'Notification', 'name': spec['name'], 'subject': spec['subject'], 'document_type': spec['document_type'], 'event': 'Value Change', 'value_changed': 'workflow_state', 'condition': 'doc.workflow_state == "{}"'.format(spec['state']), 'channel': 'Email', 'sender': _SENDER_ACCOUNT, # In-app bell notifications for the same step are already sent precisely # (organization-scoped) by sidrah_business.api._send_notification — leaving # this off avoids a second, broader-audience bell entry for the same event. 'send_system_notification': 0, 'message_type': 'Markdown', 'message': '

{{ doc.title or doc.name }} — {}

'.format(spec['state']), 'attach_print': 0, 'recipients': spec['recipients'], }).insert(ignore_permissions=True) frappe.db.commit()