From 670116881b27d4c6adea4cc8ca9e5311ad21c165 Mon Sep 17 00:00:00 2001 From: NaseeraVP Date: Tue, 7 Apr 2026 13:06:37 +0530 Subject: [PATCH 1/3] feat:created Incident Report DocType --- .../doctype/incident_report/__init__.py | 0 .../incident_report/incident_report.js | 17 +++ .../incident_report/incident_report.json | 112 ++++++++++++++++++ .../incident_report/incident_report.py | 15 +++ .../incident_report/test_incident_report.py | 9 ++ 5 files changed, 153 insertions(+) create mode 100644 gams/general_administration_management_system/doctype/incident_report/__init__.py create mode 100644 gams/general_administration_management_system/doctype/incident_report/incident_report.js create mode 100644 gams/general_administration_management_system/doctype/incident_report/incident_report.json create mode 100644 gams/general_administration_management_system/doctype/incident_report/incident_report.py create mode 100644 gams/general_administration_management_system/doctype/incident_report/test_incident_report.py diff --git a/gams/general_administration_management_system/doctype/incident_report/__init__.py b/gams/general_administration_management_system/doctype/incident_report/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gams/general_administration_management_system/doctype/incident_report/incident_report.js b/gams/general_administration_management_system/doctype/incident_report/incident_report.js new file mode 100644 index 0000000..6b000d0 --- /dev/null +++ b/gams/general_administration_management_system/doctype/incident_report/incident_report.js @@ -0,0 +1,17 @@ +// Copyright (c) 2026, efeone and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Incident Report', { + onload: function(frm) { + if (!frm.doc.reported_by) { + frappe.db.get_value('Employee', + { user_id: frappe.session.user }, + 'name' + ).then(r => { + if (r.message) { + frm.set_value('reported_by', r.message.name); + } + }); + } + } +}); \ No newline at end of file diff --git a/gams/general_administration_management_system/doctype/incident_report/incident_report.json b/gams/general_administration_management_system/doctype/incident_report/incident_report.json new file mode 100644 index 0000000..c2365ef --- /dev/null +++ b/gams/general_administration_management_system/doctype/incident_report/incident_report.json @@ -0,0 +1,112 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "INC-.YYYY.-.####", + "creation": "2026-04-07 11:47:42.488696", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "incident_title", + "incident_type", + "reported_by", + "incident_date", + "description", + "column_break_ujev", + "assigned_to", + "resolution_date", + "resolution_notes", + "status" + ], + "fields": [ + { + "fieldname": "incident_title", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Incident Title", + "reqd": 1 + }, + { + "fieldname": "incident_type", + "fieldtype": "Select", + "label": "Incident Type", + "options": "Facility\nSecurity\nIT\nHR\nOther", + "reqd": 1 + }, + { + "fieldname": "reported_by", + "fieldtype": "Link", + "label": "Reported By", + "options": "Employee", + "reqd": 1 + }, + { + "default": "Today", + "fieldname": "incident_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Incident Date", + "reqd": 1 + }, + { + "fieldname": "description", + "fieldtype": "Long Text", + "label": "Description", + "reqd": 1 + }, + { + "fieldname": "assigned_to", + "fieldtype": "Link", + "label": "Assigned To", + "options": "Employee" + }, + { + "fieldname": "resolution_date", + "fieldtype": "Date", + "label": "Resolution Date" + }, + { + "fieldname": "resolution_notes", + "fieldtype": "Long Text", + "label": "Resolution Notes" + }, + { + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Status", + "options": "Open\nIn Progress\nResolved\nClosed" + }, + { + "fieldname": "column_break_ujev", + "fieldtype": "Column Break" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2026-04-07 13:12:33.198131", + "modified_by": "Administrator", + "module": "General Administration Management System", + "name": "Incident Report", + "naming_rule": "Expression (old style)", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/gams/general_administration_management_system/doctype/incident_report/incident_report.py b/gams/general_administration_management_system/doctype/incident_report/incident_report.py new file mode 100644 index 0000000..8f88310 --- /dev/null +++ b/gams/general_administration_management_system/doctype/incident_report/incident_report.py @@ -0,0 +1,15 @@ +# Copyright (c) 2026, efeone and contributors +# For license information, please see license.txt + +import frappe +from frappe.model.document import Document +from frappe.utils import today + +class IncidentReport(Document): + + def on_update(self): + ''' + Auto set resolution date when status is Resolved +''' + if self.status == "Resolved" and not self.resolution_date: + self.resolution_date = today() \ No newline at end of file diff --git a/gams/general_administration_management_system/doctype/incident_report/test_incident_report.py b/gams/general_administration_management_system/doctype/incident_report/test_incident_report.py new file mode 100644 index 0000000..440ce57 --- /dev/null +++ b/gams/general_administration_management_system/doctype/incident_report/test_incident_report.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, efeone and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestIncidentReport(FrappeTestCase): + pass From f7074a7914afcba6dcbfc4fbdc3da1efee78932e Mon Sep 17 00:00:00 2001 From: NaseeraVP Date: Tue, 7 Apr 2026 14:00:20 +0530 Subject: [PATCH 2/3] feat:created GAMS Manager role --- .../incident_report/incident_report.js | 26 +++++++------- .../incident_report/incident_report.py | 5 +-- gams/hooks.py | 7 +++- gams/setup.py | 34 +++++++++++++++++++ 4 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 gams/setup.py diff --git a/gams/general_administration_management_system/doctype/incident_report/incident_report.js b/gams/general_administration_management_system/doctype/incident_report/incident_report.js index 6b000d0..ac56c63 100644 --- a/gams/general_administration_management_system/doctype/incident_report/incident_report.js +++ b/gams/general_administration_management_system/doctype/incident_report/incident_report.js @@ -2,16 +2,16 @@ // For license information, please see license.txt frappe.ui.form.on('Incident Report', { - onload: function(frm) { - if (!frm.doc.reported_by) { - frappe.db.get_value('Employee', - { user_id: frappe.session.user }, - 'name' - ).then(r => { - if (r.message) { - frm.set_value('reported_by', r.message.name); - } - }); - } - } -}); \ No newline at end of file + onload: function(frm) { + if (!frm.doc.reported_by) { + frappe.db.get_value('Employee', + { user_id: frappe.session.user }, + 'name' + ).then(r => { + if (r.message) { + frm.set_value('reported_by', r.message.name); + } + }); + } + } +}); diff --git a/gams/general_administration_management_system/doctype/incident_report/incident_report.py b/gams/general_administration_management_system/doctype/incident_report/incident_report.py index 8f88310..c4850a9 100644 --- a/gams/general_administration_management_system/doctype/incident_report/incident_report.py +++ b/gams/general_administration_management_system/doctype/incident_report/incident_report.py @@ -10,6 +10,7 @@ class IncidentReport(Document): def on_update(self): ''' Auto set resolution date when status is Resolved -''' + ''' if self.status == "Resolved" and not self.resolution_date: - self.resolution_date = today() \ No newline at end of file + self.resolution_date = today() + diff --git a/gams/hooks.py b/gams/hooks.py index c51dd46..df87a72 100644 --- a/gams/hooks.py +++ b/gams/hooks.py @@ -85,10 +85,15 @@ # before_install = "gams.install.before_install" # after_install = "gams.install.after_install" +# Migration +#------------ + +after_migrate = "gams.setup.after_migrate" + # Uninstallation # ------------ -# before_uninstall = "gams.uninstall.before_uninstall" +before_uninstall = "gams.uninstall.before_uninstall" # after_uninstall = "gams.uninstall.after_uninstall" # Integration Setup diff --git a/gams/setup.py b/gams/setup.py new file mode 100644 index 0000000..ae7bcf7 --- /dev/null +++ b/gams/setup.py @@ -0,0 +1,34 @@ +import frappe + +def after_migrate(): + create_custom_roles(get_gams_roles()) + +def before_migrate(): + pass + +def create_custom_roles(roles): + for role in roles: + if not frappe.db.exists("Role", role): + role_doc = frappe.get_doc({ + "doctype": "Role", + "role_name": role + }) + role_doc.insert(ignore_permissions=True) + + frappe.db.commit() + +def create_property_setters(property_setter_datas): + for data in property_setter_datas: + if frappe.db.exists("Property Setter", data): + continue + + ps = frappe.new_doc("Property Setter") + ps.update(data) + ps.flags.ignore_permissions = True + ps.insert() + +def get_gams_roles(): + return [ + "GAMS Manager" + ] + From 411d65b47e8987a0eeb96cadbc2992bcf0220fcb Mon Sep 17 00:00:00 2001 From: NaseeraVP Date: Tue, 7 Apr 2026 17:57:05 +0530 Subject: [PATCH 3/3] feat:Implemented email notifications for incident assignment and resolution --- .../incident_report/incident_report.py | 83 ++++++++++++++++++- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/gams/general_administration_management_system/doctype/incident_report/incident_report.py b/gams/general_administration_management_system/doctype/incident_report/incident_report.py index c4850a9..2117e93 100644 --- a/gams/general_administration_management_system/doctype/incident_report/incident_report.py +++ b/gams/general_administration_management_system/doctype/incident_report/incident_report.py @@ -3,14 +3,89 @@ import frappe from frappe.model.document import Document -from frappe.utils import today +from frappe.utils import today, get_url_to_form + class IncidentReport(Document): def on_update(self): ''' - Auto set resolution date when status is Resolved + Handle resolution date + email notification on Assign and Resolve actions + ''' + if not self.has_value_changed("status"): + return + + if self.status == "Resolved": + if not self.resolution_date: + self.db_set("resolution_date", today()) + + if self.status == "In Progress": + if self.resolution_date: + self.db_set("resolution_date", None) + + if self.status == "In Progress" and self.assigned_to: + email = self.get_employee_email(self.assigned_to) + + if email: + frappe.sendmail( + recipients=[email], + subject=f"Incident {self.name} Assigned to You", + message=self.get_assign_message(), + now=True + ) + + if self.status == "Resolved" and self.reported_by: + email = self.get_employee_email(self.reported_by) + + if email: + frappe.sendmail( + recipients=[email], + subject=f"Incident {self.name} Resolved", + message=self.get_resolve_message(), + now=True + ) + + def get_employee_email(self, employee): + ''' + Get the email of the employee + ''' + user = frappe.db.get_value("Employee", employee, "user_id") + if user: + return frappe.db.get_value("User", user, "email") + return None + + def get_assign_message(self): ''' - if self.status == "Resolved" and not self.resolution_date: - self.resolution_date = today() + Message to be sent to the assignee when the incident is assigned to them + ''' + return f""" +

Hello,

+

An incident has been assigned to you.

+ +

ID: {self.name}

+

Title: {self.incident_title}

+ +

+ + View Incident + +

+ """ + + def get_resolve_message(self): + ''' + Message to be sent to the reporter when the incident is resolved + ''' + return f""" +

Hello,

+

Your reported incident has been resolved.

+ +

ID: {self.name}

+

Resolution: {self.resolution_notes or "N/A"}

+

+ + View Incident + +

+ """