From b0636edaf74edbe155bf52591b4e88729fb3f190 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 16 Dec 2013 13:51:09 +0530 Subject: [PATCH] [minor] [scheduler] send scheduler errors as email digest --- patches/1311/p07_scheduler_errors_digest.py | 23 +++++++++ patches/1311/p08_email_digest_recipients.py | 11 +++++ patches/patch_list.py | 2 + setup/doctype/email_digest/email_digest.js | 4 +- setup/doctype/email_digest/email_digest.py | 27 +++++++---- setup/doctype/email_digest/email_digest.txt | 53 ++++++++++++++++----- setup/page/setup_wizard/setup_wizard.py | 19 ++++++-- startup/bean_handlers.py | 3 +- startup/schedule_handlers.py | 11 ++--- 9 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 patches/1311/p07_scheduler_errors_digest.py create mode 100644 patches/1311/p08_email_digest_recipients.py diff --git a/patches/1311/p07_scheduler_errors_digest.py b/patches/1311/p07_scheduler_errors_digest.py new file mode 100644 index 0000000000..7cfa251847 --- /dev/null +++ b/patches/1311/p07_scheduler_errors_digest.py @@ -0,0 +1,23 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + from webnotes.profile import get_system_managers + system_managers = get_system_managers(only_name=True) + if not system_managers: + return + + # scheduler errors digest + edigest = webnotes.new_bean("Email Digest") + edigest.doc.fields.update({ + "name": "Scheduler Errors", + "company": webnotes.conn.get_default("company"), + "frequency": "Daily", + "enabled": 1, + "recipient_list": "\n".join(system_managers), + "scheduler_errors": 1 + }) + edigest.insert() \ No newline at end of file diff --git a/patches/1311/p08_email_digest_recipients.py b/patches/1311/p08_email_digest_recipients.py new file mode 100644 index 0000000000..fad540844f --- /dev/null +++ b/patches/1311/p08_email_digest_recipients.py @@ -0,0 +1,11 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + from webnotes.utils import extract_email_id + for name, recipients in webnotes.conn.sql("""select name, recipient_list from `tabEmail Digest`"""): + recipients = "\n".join([extract_email_id(r) for r in recipients.split("\n")]) + webnotes.conn.set_value("Email Digest", name, "recipient_list", recipients) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 9400e08872..9df0207979 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -258,4 +258,6 @@ patch_list = [ "execute:webnotes.delete_doc('Report', 'Stock Ledger') #2013-11-29", "execute:webnotes.delete_doc('Report', 'Payment Collection With Ageing')", "execute:webnotes.delete_doc('Report', 'Payment Made With Ageing')", + "patches.1311.p07_scheduler_errors_digest", + "patches.1311.p08_email_digest_recipients", ] \ No newline at end of file diff --git a/setup/doctype/email_digest/email_digest.js b/setup/doctype/email_digest/email_digest.js index 3367a7237a..79cc681985 100644 --- a/setup/doctype/email_digest/email_digest.js +++ b/setup/doctype/email_digest/email_digest.js @@ -70,8 +70,10 @@ cur_frm.cscript.addremove_recipients = function(doc, dt, dn) { check.checked = 1; add_or_update = 'Update'; } + var fullname = wn.user.full_name(v.name); + if(fullname !== v.name) v.name = fullname + " <" + v.name + ">"; if(v.enabled==0) { - v.name = "" + v.name + " (disabled user)" + v.name = repl(" %(name)s (disabled user)", {name: v.name}); } var profile = $a($td(tab, i+1, 1), 'span', '', '', v.name); //profile.onclick = function() { check.checked = !check.checked; } diff --git a/setup/doctype/email_digest/email_digest.py b/setup/doctype/email_digest/email_digest.py index a9720ae005..082b92fb7f 100644 --- a/setup/doctype/email_digest/email_digest.py +++ b/setup/doctype/email_digest/email_digest.py @@ -19,16 +19,16 @@ content_sequence = [ ["Selling", ["new_leads", "new_enquiries", "new_quotations", "new_sales_orders"]], ["Stock", ["new_delivery_notes", "new_purchase_receipts", "new_stock_entries"]], ["Support", ["new_communications", "new_support_tickets", "open_tickets"]], - ["Projects", ["new_projects"]] + ["Projects", ["new_projects"]], + ["System", ["scheduler_errors"]], ] user_specific_content = ["calendar_events", "todo_list"] -digest_template = """\ - -

%(digest)s

-

%(date)s

+digest_template = """ +

%(name)s

%(company)s

+

%(date)s


%(with_value)s %(no_value)s @@ -53,10 +53,10 @@ class DocType(DocListController): def get_profiles(self): """get list of profiles""" - import webnotes profile_list = webnotes.conn.sql(""" select name, enabled from tabProfile where docstatus=0 and name not in ('Administrator', 'Guest') + and user_type = "System User" order by enabled desc, name asc""", as_dict=1) if self.doc.recipient_list: @@ -81,7 +81,9 @@ class DocType(DocListController): msg_for_this_receipient = self.get_msg_html(self.get_user_specific_content(user_id) + \ common_msg) from webnotes.utils.email_lib import sendmail - sendmail(recipients=user_id, subject="[ERPNext] " + (self.doc.frequency + " Digest"), + sendmail(recipients=user_id, + subject="[ERPNext] [{frequency} Digest] {name}".format( + frequency=self.doc.frequency, name=self.doc.name), msg=msg_for_this_receipient) def get_digest_msg(self): @@ -123,7 +125,7 @@ class DocType(DocListController): if with_value: with_value = "\n".join(with_value) else: - with_value = "

There were no updates in the items selected for this digest.

" + with_value = "

There were no updates in the items selected for this digest.


" # seperate out no value items no_value = [o[1] for o in out if not o[0]] @@ -138,7 +140,8 @@ class DocType(DocListController): "date": date, "company": self.doc.company, "with_value": with_value, - "no_value": no_value or "" + "no_value": no_value or "", + "name": self.doc.name } return msg @@ -452,6 +455,10 @@ class DocType(DocListController): t for t in open_tickets]) else: return 0, "No Open Tickets!" + + def get_scheduler_errors(self): + import webnotes.utils.scheduler + return webnotes.utils.scheduler.get_error_report(self.from_date, self.to_date) def onload(self): self.get_next_sending() @@ -470,4 +477,4 @@ def send(): where enabled=1 and docstatus<2""", as_list=1): ed_obj = get_obj('Email Digest', ed[0]) if (now_date == ed_obj.get_next_sending()): - ed_obj.send() + ed_obj.send() \ No newline at end of file diff --git a/setup/doctype/email_digest/email_digest.txt b/setup/doctype/email_digest/email_digest.txt index f71d82a0e3..b04885a4c9 100644 --- a/setup/doctype/email_digest/email_digest.txt +++ b/setup/doctype/email_digest/email_digest.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-21 14:15:31", "docstatus": 0, - "modified": "2013-07-05 14:36:13", + "modified": "2013-12-16 12:37:43", "modified_by": "Administrator", "owner": "Administrator" }, @@ -100,11 +100,10 @@ "label": "Add/Remove Recipients" }, { - "description": "Check all the items below that you want to send in this digest.", "doctype": "DocField", - "fieldname": "select_digest_content", + "fieldname": "accounts", "fieldtype": "Section Break", - "label": "Select Digest Content" + "label": "Accounts" }, { "doctype": "DocField", @@ -178,7 +177,7 @@ "doctype": "DocField", "fieldname": "section_break_20", "fieldtype": "Section Break", - "options": "Simple" + "label": "Buying & Selling" }, { "doctype": "DocField", @@ -234,6 +233,12 @@ "fieldtype": "Check", "label": "New Sales Orders" }, + { + "doctype": "DocField", + "fieldname": "section_break_34", + "fieldtype": "Section Break", + "label": "Inventory & Support" + }, { "doctype": "DocField", "fieldname": "stock_module", @@ -258,12 +263,6 @@ "fieldtype": "Check", "label": "New Stock Entries" }, - { - "doctype": "DocField", - "fieldname": "section_break_34", - "fieldtype": "Section Break", - "options": "Simple" - }, { "doctype": "DocField", "fieldname": "support_module", @@ -288,6 +287,12 @@ "fieldtype": "Check", "label": "New Communications" }, + { + "doctype": "DocField", + "fieldname": "section_break_40", + "fieldtype": "Section Break", + "label": "Projects & System" + }, { "doctype": "DocField", "fieldname": "projects_module", @@ -302,7 +307,25 @@ }, { "doctype": "DocField", - "fieldname": "utilities_module", + "fieldname": "core_module", + "fieldtype": "Column Break", + "label": "System" + }, + { + "doctype": "DocField", + "fieldname": "scheduler_errors", + "fieldtype": "Check", + "label": "Scheduler Failed Events" + }, + { + "doctype": "DocField", + "fieldname": "user_specific", + "fieldtype": "Section Break", + "label": "User Specific" + }, + { + "doctype": "DocField", + "fieldname": "general", "fieldtype": "Column Break", "label": "General" }, @@ -318,6 +341,12 @@ "fieldtype": "Check", "label": "To Do List" }, + { + "doctype": "DocField", + "fieldname": "stub", + "fieldtype": "Column Break", + "label": "Stub" + }, { "cancel": 1, "create": 1, diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index bf149059a1..b5133ef479 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -171,7 +171,7 @@ def create_feed_and_todo(): def create_email_digest(): from webnotes.profile import get_system_managers - system_managers = get_system_managers() + system_managers = get_system_managers(only_name=True) if not system_managers: return @@ -186,10 +186,23 @@ def create_email_digest(): }) for fieldname in edigest.meta.get_fieldnames({"fieldtype": "Check"}): - edigest.doc.fields[fieldname] = 1 + if fieldname != "scheduler_errors": + edigest.doc.fields[fieldname] = 1 edigest.insert() - + + # scheduler errors digest + edigest = webnotes.new_bean("Email Digest") + edigest.doc.fields.update({ + "name": "Scheduler Errors", + "company": webnotes.conn.get_default("company"), + "frequency": "Daily", + "recipient_list": "\n".join(system_managers), + "scheduler_errors": 1, + "enabled": 1 + }) + edigest.insert() + def get_fy_details(fy_start_date, fy_end_date): start_year = getdate(fy_start_date).year if start_year == getdate(fy_end_date).year: diff --git a/startup/bean_handlers.py b/startup/bean_handlers.py index 06d27343d8..678c8aa5b4 100644 --- a/startup/bean_handlers.py +++ b/startup/bean_handlers.py @@ -13,4 +13,5 @@ def on_method(bean, method): clear_doctype_notifications(bean.controller, method) if bean.doc.doctype=="Stock Entry" and method in ("on_submit", "on_cancel"): - update_completed_qty(bean.controller, method) \ No newline at end of file + update_completed_qty(bean.controller, method) + \ No newline at end of file diff --git a/startup/schedule_handlers.py b/startup/schedule_handlers.py index cdb0e5d5dd..252a091547 100644 --- a/startup/schedule_handlers.py +++ b/startup/schedule_handlers.py @@ -34,10 +34,6 @@ def execute_daily(): from core.doctype.notification_count.notification_count import delete_notification_count_for delete_notification_count_for("Event") - # email digest - from setup.doctype.email_digest.email_digest import send - run_fn(send) - # run recurring invoices from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices run_fn(manage_recurring_invoices) @@ -53,10 +49,11 @@ def execute_daily(): # check reorder level from stock.utils import reorder_item run_fn(reorder_item) + + # email digest + from setup.doctype.email_digest.email_digest import send + run_fn(send) - # scheduler error - scheduler.report_errors() - def execute_weekly(): from setup.doctype.backup_manager.backup_manager import take_backups_weekly run_fn(take_backups_weekly)