email digest for todo and calendar
diff --git a/setup/doctype/email_digest/email_digest.py b/setup/doctype/email_digest/email_digest.py
index 612677d..a140669 100644
--- a/setup/doctype/email_digest/email_digest.py
+++ b/setup/doctype/email_digest/email_digest.py
@@ -16,19 +16,28 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import fmt_money, formatdate, now_datetime, cstr, esc
+from webnotes import _
+from webnotes.utils import fmt_money, formatdate, now_datetime, cstr, esc, get_url_to_form
+from webnotes.utils.dateutils import datetime_in_user_format
from datetime import timedelta
from dateutil.relativedelta import relativedelta
-content_sequence = ["income_year_to_date", "bank_balance",
- "income", "expenses_booked", "collections", "payments",
- "invoiced_amount", "payables",
- "new_leads", "new_enquiries", "new_quotations", "new_sales_orders",
- "new_delivery_notes", "new_purchase_requests", "new_supplier_quotations",
- "new_purchase_orders", "new_purchase_receipts", "new_stock_entries",
- "new_support_tickets", "new_communications", "new_projects", "open_tickets"]
+content_sequence = [
+ ["Accounts", ["income_year_to_date", "bank_balance",
+ "income", "expenses_booked", "collections", "payments",
+ "invoiced_amount", "payables"]],
+ ["Buying", ["new_purchase_requests", "new_supplier_quotations", "new_purchase_orders"]],
+ ["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"]]
+]
-digest_template = """<h2>%(digest)s</h2>
+user_specific_content = ["calendar_events", "todo_list"]
+
+digest_template = """\
+<style>p.ed-indent { margin-right: 17px; }</style>
+<h2>%(digest)s</h2>
<p style='color: grey'>%(date)s</p>
<h4>%(company)s</h4>
<hr>
@@ -47,6 +56,10 @@
class DocType:
def __init__(self, doc, doclist=[]):
self.doc, self.doclist = doc, doclist
+ self.from_date, self.to_date = self.get_from_to_date()
+ self.future_from_date, self.future_to_date = self.get_future_from_to_date()
+ self.currency = webnotes.conn.get_value("Company", self.doc.company,
+ "default_currency")
def get_profiles(self):
"""get list of profiles"""
@@ -72,26 +85,49 @@
recipients = filter(lambda r: r in valid_users,
self.doc.recipient_list.split("\n"))
+ common_msg = self.get_common_content()
if recipients:
- from webnotes.utils.email_lib import sendmail
- sendmail(recipients=recipients, subject=(self.doc.frequency + " Digest"),
- sender="ERPNext Notifications <notifications+email_digest@erpnext.com>",
- msg=self.get_digest_msg())
-
+ for user_id in recipients:
+ 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=(self.doc.frequency + " Digest"),
+ sender="ERPNext Notifications <notifications+email_digest@erpnext.com>",
+ msg=msg_for_this_receipient)
+
def get_digest_msg(self):
- """"""
- self.from_date, self.to_date = self.get_from_to_date()
- self.currency = webnotes.conn.get_value("Company", self.doc.company,
- "default_currency")
+ return self.get_msg_html(self.get_user_specific_content(webnotes.session.user) + \
+ self.get_common_content())
+
+ def get_common_content(self):
+ out = []
+ for module, content in content_sequence:
+ module_out = []
+ for ctype in content:
+ if self.doc.fields.get(ctype) and hasattr(self, "get_"+ctype):
+ module_out.append(getattr(self, "get_"+ctype)())
+ if any([m[0] for m in module_out]):
+ out += [[1, "<h4>" + _(module) + "</h4>"]] + module_out + [[1, "<hr>"]]
+ else:
+ out += module_out
+
+ return out
+
+ def get_user_specific_content(self, user_id):
+ original_session_user = webnotes.session.user
+
+ # setting session user for role base event fetching
+ webnotes.session.user = user_id
out = []
- for ctype in content_sequence:
+ for ctype in user_specific_content:
if self.doc.fields.get(ctype) and hasattr(self, "get_"+ctype):
- # appends [not "no updates", html]
- out.append(getattr(self, "get_"+ctype)())
+ out.append(getattr(self, "get_"+ctype)(user_id))
+
+ webnotes.session.user = original_session_user
- return self.get_msg_html(out)
-
+ return out
+
def get_msg_html(self, out):
with_value = [o[1] for o in out if o[0]]
@@ -103,7 +139,7 @@
# seperate out no value items
no_value = [o[1] for o in out if not o[0]]
if no_value:
- no_value = """<hr><h4>No Updates For:</h4><br>""" + "\n".join(no_value)
+ no_value = """<h4>No Updates For:</h4>""" + "\n".join(no_value)
date = self.doc.frequency == "Daily" and formatdate(self.from_date) or \
"%s to %s" % (formatdate(self.from_date), formatdate(self.to_date))
@@ -249,6 +285,39 @@
def get_new_projects(self):
return self.get_new_count("Project", "New Projects", False)
+
+ def get_calendar_events(self, user_id):
+ from core.doctype.event.event import get_events
+ events = get_events(self.future_from_date, self.future_to_date)
+
+ html = ""
+ if events:
+ for i, e in enumerate(events):
+ if i>=10:
+ break
+ if e.all_day:
+ html += """<p>%s [%s (%s)]</p>""" % \
+ (e.subject, datetime_in_user_format(e.starts_on), _("All Day"))
+ else:
+ html += "<p>%s [%s - %s]</p>" % \
+ (e.subject, datetime_in_user_format(e.starts_on), datetime_in_user_format(e.ends_on))
+
+ return html and 1 or 0, "<h4>Upcoming Calendar Events (max 10):</h4>" + html + "<hr>"
+
+ def get_todo_list(self, user_id):
+ from utilities.page.todo.todo import get
+ todo_list = get()
+
+ html = ""
+ if todo_list:
+ for i, todo in enumerate([todo for todo in todo_list if not todo.checked]):
+ if i>= 10:
+ break
+ html += "<p>%s: %s</p>" % (todo.priority, todo.description or \
+ get_url_to_form(todo.reference_type, todo.reference_name))
+
+
+ return html and 1 or 0, "<h4>To Do (max 10):</h4>" + html + "<hr>"
def get_new_count(self, doctype, label, filter_by_company=True):
if filter_by_company:
@@ -330,6 +399,26 @@
to_date = today - relativedelta(days=today.day)
return from_date, to_date
+
+ def get_future_from_to_date(self):
+ today = now_datetime().date()
+
+ # decide from date based on email digest frequency
+ if self.doc.frequency == "Daily":
+ # from date, to_date is today
+ from_date = to_date = today
+ elif self.doc.frequency == "Weekly":
+ # from date is the current week's monday
+ from_date = today - timedelta(days=today.weekday())
+ # to date is the current week's sunday
+ to_date = from_date + timedelta(days=6)
+ else:
+ # from date is the 1st day of the current month
+ from_date = today - relativedelta(days=today.day-1)
+ # to date is the last day of the current month
+ to_date = from_date + relativedelta(days=-1, months=1)
+
+ return from_date, to_date
def get_next_sending(self):
from_date, to_date = self.get_from_to_date()
diff --git a/setup/doctype/email_digest/email_digest.txt b/setup/doctype/email_digest/email_digest.txt
index b03c542..316a840 100644
--- a/setup/doctype/email_digest/email_digest.txt
+++ b/setup/doctype/email_digest/email_digest.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-01-10 16:34:23",
+ "creation": "2013-01-25 11:35:08",
"docstatus": 0,
- "modified": "2013-01-22 14:56:01",
+ "modified": "2013-02-16 14:43:52",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -23,19 +23,14 @@
"permlevel": 0
},
{
- "cancel": 1,
- "create": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Email Digest",
"parentfield": "permissions",
"parenttype": "DocType",
- "permlevel": 0,
"read": 1,
- "report": 1,
"role": "System Manager",
- "submit": 0,
- "write": 1
+ "submit": 0
},
{
"doctype": "DocType",
@@ -112,92 +107,9 @@
},
{
"doctype": "DocField",
- "fieldname": "new_leads",
- "fieldtype": "Check",
- "label": "New Leads"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_enquiries",
- "fieldtype": "Check",
- "label": "New Enquiries"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_quotations",
- "fieldtype": "Check",
- "label": "New Quotations"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_sales_orders",
- "fieldtype": "Check",
- "label": "New Sales Orders"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_delivery_notes",
- "fieldtype": "Check",
- "label": "New Delivery Notes"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_purchase_requests",
- "fieldtype": "Check",
- "label": "New Purchase Requests"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_supplier_quotations",
- "fieldtype": "Check",
- "label": "New Supplier Quotations"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_purchase_orders",
- "fieldtype": "Check",
- "label": "New Purchase Orders"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_purchase_receipts",
- "fieldtype": "Check",
- "label": "New Purchase Receipts"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_stock_entries",
- "fieldtype": "Check",
- "label": "New Stock Entries"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_support_tickets",
- "fieldtype": "Check",
- "label": "New Support Tickets"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_communications",
- "fieldtype": "Check",
- "label": "New Communications"
- },
- {
- "doctype": "DocField",
- "fieldname": "new_projects",
- "fieldtype": "Check",
- "label": "New Projects"
- },
- {
- "doctype": "DocField",
- "fieldname": "open_tickets",
- "fieldtype": "Check",
- "label": "Open Tickets"
- },
- {
- "doctype": "DocField",
- "fieldname": "cb1",
- "fieldtype": "Column Break"
+ "fieldname": "accounts_module",
+ "fieldtype": "Column Break",
+ "label": "Accounts"
},
{
"doctype": "DocField",
@@ -248,6 +160,162 @@
"label": "Payables"
},
{
- "doctype": "DocPerm"
+ "doctype": "DocField",
+ "fieldname": "buying_module",
+ "fieldtype": "Column Break",
+ "label": "Buying"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_purchase_requests",
+ "fieldtype": "Check",
+ "label": "New Purchase Requests"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_supplier_quotations",
+ "fieldtype": "Check",
+ "label": "New Supplier Quotations"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_purchase_orders",
+ "fieldtype": "Check",
+ "label": "New Purchase Orders"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "selling_module",
+ "fieldtype": "Column Break",
+ "label": "Selling"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_leads",
+ "fieldtype": "Check",
+ "label": "New Leads"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_enquiries",
+ "fieldtype": "Check",
+ "label": "New Enquiries"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_quotations",
+ "fieldtype": "Check",
+ "label": "New Quotations"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_sales_orders",
+ "fieldtype": "Check",
+ "label": "New Sales Orders"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "section_break_34",
+ "fieldtype": "Section Break",
+ "options": "Simple"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "stock_module",
+ "fieldtype": "Column Break",
+ "label": "Stock"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_delivery_notes",
+ "fieldtype": "Check",
+ "label": "New Delivery Notes"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_purchase_receipts",
+ "fieldtype": "Check",
+ "label": "New Purchase Receipts"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_stock_entries",
+ "fieldtype": "Check",
+ "label": "New Stock Entries"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "support_module",
+ "fieldtype": "Column Break",
+ "label": "Support"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_support_tickets",
+ "fieldtype": "Check",
+ "label": "New Support Tickets"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "open_tickets",
+ "fieldtype": "Check",
+ "label": "Open Tickets"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_communications",
+ "fieldtype": "Check",
+ "label": "New Communications"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "projects_module",
+ "fieldtype": "Column Break",
+ "label": "Projects"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "new_projects",
+ "fieldtype": "Check",
+ "label": "New Projects"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "section_break_41",
+ "fieldtype": "Section Break",
+ "options": "Simple"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "utilities_module",
+ "fieldtype": "Column Break",
+ "label": "General"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "calendar_events",
+ "fieldtype": "Check",
+ "label": "Calendar Events"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "todo_list",
+ "fieldtype": "Check",
+ "label": "To Do List"
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "permlevel": 0,
+ "report": 1,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "doctype": "DocPerm",
+ "permlevel": 1
}
]
\ No newline at end of file