Merge pull request #4113 from rmehta/email-digest-cleanup
[cleanup] Email Digest
This commit is contained in:
commit
b4c0e94e99
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe, json
|
import frappe, json
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form, \
|
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_link_to_form, \
|
||||||
comma_or, get_fullname
|
comma_or, get_fullname
|
||||||
from frappe import msgprint
|
from frappe import msgprint
|
||||||
from erpnext.hr.utils import set_employee_name
|
from erpnext.hr.utils import set_employee_name
|
||||||
@ -164,7 +164,7 @@ class LeaveApplication(Document):
|
|||||||
|
|
||||||
def _get_message(url=False):
|
def _get_message(url=False):
|
||||||
if url:
|
if url:
|
||||||
name = get_url_to_form(self.doctype, self.name)
|
name = get_link_to_form(self.doctype, self.name)
|
||||||
else:
|
else:
|
||||||
name = self.name
|
name = self.name
|
||||||
|
|
||||||
@ -184,8 +184,8 @@ class LeaveApplication(Document):
|
|||||||
name = self.name
|
name = self.name
|
||||||
employee_name = cstr(employee.employee_name)
|
employee_name = cstr(employee.employee_name)
|
||||||
if url:
|
if url:
|
||||||
name = get_url_to_form(self.doctype, self.name)
|
name = get_link_to_form(self.doctype, self.name)
|
||||||
employee_name = get_url_to_form("Employee", self.employee, label=employee_name)
|
employee_name = get_link_to_form("Employee", self.employee, label=employee_name)
|
||||||
|
|
||||||
return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name)
|
return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name)
|
||||||
|
|
||||||
|
@ -218,3 +218,4 @@ erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order
|
|||||||
erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
|
erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
|
||||||
erpnext.patches.v6_4.fix_duplicate_bins
|
erpnext.patches.v6_4.fix_duplicate_bins
|
||||||
erpnext.patches.v6_4.fix_sales_order_maintenance_status
|
erpnext.patches.v6_4.fix_sales_order_maintenance_status
|
||||||
|
erpnext.patches.v6_4.email_digest_update
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.email import sendmail_to_system_managers
|
from frappe.email import sendmail_to_system_managers
|
||||||
from frappe.utils import get_url_to_form
|
from frappe.utils import get_link_to_form
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
wrong_records = []
|
wrong_records = []
|
||||||
@ -15,7 +15,7 @@ def execute():
|
|||||||
and modified >= '2015-02-17' and docstatus=1""".format(dt))
|
and modified >= '2015-02-17' and docstatus=1""".format(dt))
|
||||||
|
|
||||||
if records:
|
if records:
|
||||||
records = [get_url_to_form(dt, d) for d in records]
|
records = [get_link_to_form(dt, d) for d in records]
|
||||||
wrong_records.append([dt, records])
|
wrong_records.append([dt, records])
|
||||||
|
|
||||||
if wrong_records:
|
if wrong_records:
|
||||||
|
6
erpnext/patches/v6_4/email_digest_update.py
Normal file
6
erpnext/patches/v6_4/email_digest_update.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doctype("Email Digest")
|
||||||
|
frappe.db.sql("""update `tabEmail Digest` set expense_year_to_date =
|
||||||
|
income_year_to_date""")
|
@ -7,28 +7,22 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
|
|||||||
var err_msg = __("There was an error. One probable reason could be that you haven't saved the form. Please contact support@erpnext.com if the problem persists.")
|
var err_msg = __("There was an error. One probable reason could be that you haven't saved the form. Please contact support@erpnext.com if the problem persists.")
|
||||||
|
|
||||||
cur_frm.add_custom_button(__('View Now'), function() {
|
cur_frm.add_custom_button(__('View Now'), function() {
|
||||||
doc = locals[dt][dn];
|
frappe.call({
|
||||||
if(doc.__unsaved != 1) {
|
method: 'erpnext.setup.doctype.email_digest.email_digest.get_digest_msg',
|
||||||
return $c_obj(doc, 'get_digest_msg', '', function(r, rt) {
|
args: {
|
||||||
if(r.exc) {
|
name: doc.name
|
||||||
msgprint(err_msg);
|
},
|
||||||
console.log(r.exc);
|
callback: function(r) {
|
||||||
} else {
|
var d = new frappe.ui.Dialog({
|
||||||
//console.log(arguments);
|
title: __('Email Digest: ') + dn,
|
||||||
var d = new frappe.ui.Dialog({
|
width: 800
|
||||||
title: __('Email Digest: ') + dn,
|
});
|
||||||
width: 800
|
$(d.body).html(r.message);
|
||||||
});
|
d.show();
|
||||||
|
}
|
||||||
$a(d.body, 'div', '', '', r['message']);
|
});
|
||||||
|
|
||||||
d.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
msgprint(save_msg);
|
|
||||||
}
|
|
||||||
}, "icon-eye-open", "btn-default");
|
}, "icon-eye-open", "btn-default");
|
||||||
|
|
||||||
cur_frm.add_custom_button(__('Send Now'), function() {
|
cur_frm.add_custom_button(__('Send Now'), function() {
|
||||||
doc = locals[dt][dn];
|
doc = locals[dt][dn];
|
||||||
if(doc.__unsaved != 1) {
|
if(doc.__unsaved != 1) {
|
||||||
|
@ -247,14 +247,58 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Balances of Accounts of type \"Bank\" or \"Cash\"",
|
"description": "",
|
||||||
|
"fieldname": "income",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Income",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "expenses_booked",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Expense",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"description": "",
|
||||||
"fieldname": "bank_balance",
|
"fieldname": "bank_balance",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Bank/Cash Balance",
|
"label": "Bank Balance",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -275,7 +319,7 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Income Year to Date",
|
"label": "Annual Income",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -290,16 +334,16 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Income booked for the digest period",
|
"fieldname": "expense_year_to_date",
|
||||||
"fieldname": "income",
|
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Income Booked",
|
"label": "Annual Expense",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
@ -312,29 +356,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Expenses booked for the digest period",
|
"description": "",
|
||||||
"fieldname": "expenses_booked",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Expenses Booked",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"description": "Receivable / Payable account will be identified based on the field Master Type",
|
|
||||||
"fieldname": "column_break_16",
|
"fieldname": "column_break_16",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -356,7 +378,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Total amount of invoices sent to the customer during the digest period",
|
"description": "",
|
||||||
"fieldname": "invoiced_amount",
|
"fieldname": "invoiced_amount",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -378,7 +400,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Total amount of invoices received from suppliers during the digest period",
|
"description": "",
|
||||||
"fieldname": "payables",
|
"fieldname": "payables",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -395,659 +417,6 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"description": "Payments received during the digest period",
|
|
||||||
"fieldname": "collections",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Payments Received",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"description": "Payments made during the digest period",
|
|
||||||
"fieldname": "payments",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Payments Made",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "section_break_20",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Buying & Selling",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "buying_module",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Buying",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_purchase_requests",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Material Requests",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_supplier_quotations",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Supplier Quotations",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_purchase_orders",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Purchase Orders",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "selling_module",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Selling",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_leads",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Leads",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_enquiries",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Enquiries",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_quotations",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Quotations",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_sales_orders",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Sales Orders",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "section_break_34",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Inventory & Support",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "stock_module",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Stock",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_delivery_notes",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Delivery Notes",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_purchase_receipts",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Purchase Receipts",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_stock_entries",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Stock Entries",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "support_module",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Support",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_support_tickets",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Support Tickets",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "open_tickets",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Open Tickets",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_communications",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Communications",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "section_break_40",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Projects & System",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "projects_module",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Projects",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "new_projects",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "New Projects",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "core_module",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "System",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "scheduler_errors",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Scheduler Failed Events",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "user_specific",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "User Specific",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "general",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "General",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "calendar_events",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Calendar Events",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "todo_list",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "To Do List",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "stub",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Stub",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
@ -1059,7 +428,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-02-05 05:11:38.024529",
|
"modified": "2015-10-02 07:33:27.334888",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Email Digest",
|
"name": "Email Digest",
|
||||||
|
@ -4,52 +4,24 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import fmt_money, formatdate, now_datetime, cstr, esc, \
|
from frappe.utils import fmt_money, formatdate, format_time, now_datetime, \
|
||||||
get_url_to_form, get_fullname
|
get_url_to_form, get_url_to_list, flt
|
||||||
from frappe.utils.dateutils import datetime_in_user_format
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from frappe.core.doctype.user.user import STANDARD_USERS
|
from frappe.core.doctype.user.user import STANDARD_USERS
|
||||||
|
import frappe.desk.notifications
|
||||||
content_sequence = [
|
from erpnext.accounts.utils import get_balance_on
|
||||||
["Income / Expenses", ["income_year_to_date", "income", "expenses_booked"]],
|
|
||||||
["Receivables / Payables", ["collections", "payments",
|
|
||||||
"invoiced_amount", "payables"]],
|
|
||||||
["Bank Balance", ["bank_balance"]],
|
|
||||||
["Buying", ["new_purchase_requests", "new_supplier_quotations", "new_purchase_orders"]],
|
|
||||||
["CRM", ["new_leads", "new_enquiries"]],
|
|
||||||
["Selling", ["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"]],
|
|
||||||
["System", ["scheduler_errors"]],
|
|
||||||
]
|
|
||||||
|
|
||||||
user_specific_content = ["calendar_events", "todo_list"]
|
user_specific_content = ["calendar_events", "todo_list"]
|
||||||
|
|
||||||
digest_template = """<style>p.ed-indent { margin-right: 17px; }</style>
|
|
||||||
<h2>%(name)s</h2>
|
|
||||||
<h4>%(company)s</h4>
|
|
||||||
<p style='color: grey'>%(date)s</p>
|
|
||||||
<hr>
|
|
||||||
%(with_value)s
|
|
||||||
%(no_value)s
|
|
||||||
<hr>
|
|
||||||
<p style="color: #888; font-size: 90%%">To change what you see here,
|
|
||||||
create more digests, go to Setup > Email Digest</p>"""
|
|
||||||
|
|
||||||
row_template = """<p style="%(style)s">
|
|
||||||
<span>%(label)s</span>:
|
|
||||||
<span style="font-weight: bold; font-size: 110%%">
|
|
||||||
<span style="color: grey">%(currency)s</span>%(value)s
|
|
||||||
</span></p>"""
|
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
class EmailDigest(Document):
|
class EmailDigest(Document):
|
||||||
def __init__(self, arg1, arg2=None):
|
def __init__(self, arg1, arg2=None):
|
||||||
super(EmailDigest, self).__init__(arg1, arg2)
|
super(EmailDigest, self).__init__(arg1, arg2)
|
||||||
|
|
||||||
self.from_date, self.to_date = self.get_from_to_date()
|
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.set_dates()
|
||||||
|
self._accounts = {}
|
||||||
self.currency = frappe.db.get_value("Company", self.company,
|
self.currency = frappe.db.get_value("Company", self.company,
|
||||||
"default_currency")
|
"default_currency")
|
||||||
|
|
||||||
@ -77,325 +49,216 @@ class EmailDigest(Document):
|
|||||||
recipients = filter(lambda r: r in valid_users,
|
recipients = filter(lambda r: r in valid_users,
|
||||||
self.recipient_list.split("\n"))
|
self.recipient_list.split("\n"))
|
||||||
|
|
||||||
common_msg = self.get_common_content()
|
original_user = frappe.session.user
|
||||||
|
|
||||||
if recipients:
|
if recipients:
|
||||||
for user_id in recipients:
|
for user_id in recipients:
|
||||||
msg_for_this_receipient = self.get_msg_html(self.get_user_specific_content(user_id) + \
|
frappe.set_user(user_id)
|
||||||
common_msg)
|
msg_for_this_receipient = self.get_msg_html()
|
||||||
if msg_for_this_receipient:
|
if msg_for_this_receipient:
|
||||||
frappe.sendmail(recipients=user_id,
|
frappe.sendmail(
|
||||||
|
recipients=user_id,
|
||||||
subject="{frequency} Digest".format(frequency=self.frequency),
|
subject="{frequency} Digest".format(frequency=self.frequency),
|
||||||
message=msg_for_this_receipient, bulk=True)
|
message=msg_for_this_receipient,
|
||||||
|
bulk=True,
|
||||||
|
reference_doctype = self.doctype,
|
||||||
|
reference_name = self.name,
|
||||||
|
unsubscribe_message = _("Unsubscribe from this Email Digest"))
|
||||||
|
|
||||||
def get_digest_msg(self):
|
frappe.set_user(original_user)
|
||||||
return self.get_msg_html(self.get_user_specific_content(frappe.session.user) + \
|
|
||||||
self.get_common_content(), send_only_if_updates=False)
|
|
||||||
|
|
||||||
def get_common_content(self):
|
def get_msg_html(self):
|
||||||
out = []
|
"""Build email digest content"""
|
||||||
for module, content in content_sequence:
|
context = frappe._dict()
|
||||||
module_out = []
|
context.update(self.__dict__)
|
||||||
for ctype in content:
|
|
||||||
if self.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
|
self.set_title(context)
|
||||||
|
self.set_style(context)
|
||||||
|
|
||||||
def get_user_specific_content(self, user_id):
|
self.set_accounting_cards(context)
|
||||||
original_session_user = frappe.session.user
|
|
||||||
|
|
||||||
# setting session user for role base event fetching
|
context.events = self.get_calendar_events()
|
||||||
frappe.session.user = user_id
|
context.todo_list = self.get_todo_list()
|
||||||
|
context.notifications = self.get_notifications()
|
||||||
|
|
||||||
out = []
|
if not (context.events or context.todo_list or context.notifications or context.cards):
|
||||||
for ctype in user_specific_content:
|
return None
|
||||||
if self.get(ctype) and hasattr(self, "get_"+ctype):
|
|
||||||
out.append(getattr(self, "get_"+ctype)(user_id))
|
|
||||||
|
|
||||||
frappe.session.user = original_session_user
|
# style
|
||||||
|
return frappe.render_template("erpnext/setup/doctype/email_digest/templates/default.html",
|
||||||
|
context, is_path=True)
|
||||||
|
|
||||||
return out
|
def set_title(self, context):
|
||||||
|
"""Set digest title"""
|
||||||
|
if self.frequency=="Daily":
|
||||||
|
context.title = _("Daily Reminders")
|
||||||
|
context.subtitle = _("Pending activities for today")
|
||||||
|
elif self.frequency=="Weekly":
|
||||||
|
context.title = _("This Week's Summary")
|
||||||
|
context.subtitle = _("Summary for this week and pending activities")
|
||||||
|
elif self.frequency=="Monthly":
|
||||||
|
context.title = _("This Month's Summary")
|
||||||
|
context.subtitle = _("Summary for this month and pending activities")
|
||||||
|
|
||||||
def get_msg_html(self, out, send_only_if_updates=True):
|
def set_style(self, context):
|
||||||
with_value = [o[1] for o in out if o[0]]
|
"""Set standard digest style"""
|
||||||
|
context.text_muted = '#8D99A6'
|
||||||
|
context.h1 = 'margin-bottom: 30px; margin-bottom: 0'
|
||||||
|
context.label_css = '''display: inline-block; color: {text_muted};
|
||||||
|
padding: 3px 7px; margin-right: 7px;'''.format(text_muted = context.text_muted)
|
||||||
|
context.section_head = 'margin-top: 60px;'
|
||||||
|
context.line_item = 'padding: 7px 0px; margin: 0; border-bottom: 1px solid #d1d8dd;'
|
||||||
|
|
||||||
if with_value:
|
|
||||||
has_updates = True
|
|
||||||
with_value = "\n".join(with_value)
|
|
||||||
else:
|
|
||||||
has_updates = False
|
|
||||||
with_value = "<p>" + _("There were no updates in the items selected for this digest.") + "</p><hr>"
|
|
||||||
|
|
||||||
if not has_updates and send_only_if_updates:
|
def get_notifications(self):
|
||||||
return
|
"""Get notifications for user"""
|
||||||
|
notifications = frappe.desk.notifications.get_notifications()
|
||||||
|
|
||||||
# seperate out no value items
|
notifications = sorted(notifications.get("open_count_doctype", {}).items(),
|
||||||
no_value = [o[1] for o in out if not o[0]]
|
lambda a, b: 1 if a[1] < b[1] else -1)
|
||||||
if no_value:
|
|
||||||
no_value = """<h4>""" + _("No Updates For") + """:</h4>""" + "\n".join(no_value)
|
|
||||||
|
|
||||||
date = self.frequency == "Daily" and formatdate(self.from_date) or \
|
notifications = [{"key": n[0], "value": n[1],
|
||||||
"%s to %s" % (formatdate(self.from_date), formatdate(self.to_date))
|
"link": get_url_to_list(n[0])} for n in notifications if n[1]]
|
||||||
|
|
||||||
msg = digest_template % {
|
return notifications
|
||||||
"digest": self.frequency + " Digest",
|
|
||||||
"date": date,
|
|
||||||
"company": self.company,
|
|
||||||
"with_value": with_value,
|
|
||||||
"no_value": no_value or "",
|
|
||||||
"name": self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg
|
def get_calendar_events(self):
|
||||||
|
"""Get calendar events for given user"""
|
||||||
def get_income_year_to_date(self):
|
|
||||||
return self.get_income(frappe.db.get_defaults("year_start_date"),
|
|
||||||
self.meta.get_label("income_year_to_date"))
|
|
||||||
|
|
||||||
def get_bank_balance(self):
|
|
||||||
# account is of type "Bank" or "Cash"
|
|
||||||
accounts = dict([[a["name"], [a["account_name"], 0]] for a in self.get_accounts()
|
|
||||||
if a["account_type"] in ["Bank", "Cash"]])
|
|
||||||
ackeys = accounts.keys()
|
|
||||||
|
|
||||||
for gle in self.get_gl_entries(None, self.to_date):
|
|
||||||
if gle["account"] in ackeys:
|
|
||||||
accounts[gle["account"]][1] += gle["debit"] - gle["credit"]
|
|
||||||
|
|
||||||
# build html
|
|
||||||
out = self.get_html("Bank/Cash Balance as on " + formatdate(self.to_date), "", "")
|
|
||||||
for ac in ackeys:
|
|
||||||
if accounts[ac][1]:
|
|
||||||
out += "\n" + self.get_html(accounts[ac][0], self.currency,
|
|
||||||
fmt_money(accounts[ac][1]), style="margin-left: 17px")
|
|
||||||
return sum((accounts[ac][1] for ac in ackeys)), out
|
|
||||||
|
|
||||||
def get_income(self, from_date=None, label=None):
|
|
||||||
accounts = [a["name"] for a in self.get_accounts() if a["root_type"]=="Income"]
|
|
||||||
|
|
||||||
income = 0
|
|
||||||
for gle in self.get_gl_entries(from_date or self.from_date, self.to_date):
|
|
||||||
if gle["account"] in accounts:
|
|
||||||
income += gle["credit"] - gle["debit"]
|
|
||||||
|
|
||||||
return income, self.get_html(label or self.meta.get_label("income"), self.currency,
|
|
||||||
fmt_money(income))
|
|
||||||
|
|
||||||
def get_expenses_booked(self):
|
|
||||||
accounts = [a["name"] for a in self.get_accounts() if a["root_type"]=="Expense"]
|
|
||||||
|
|
||||||
expense = 0
|
|
||||||
for gle in self.get_gl_entries(self.from_date, self.to_date):
|
|
||||||
if gle["account"] in accounts:
|
|
||||||
expense += gle["debit"] - gle["credit"]
|
|
||||||
|
|
||||||
return expense, self.get_html(self.meta.get_label("expenses_booked"), self.currency,
|
|
||||||
fmt_money(expense))
|
|
||||||
|
|
||||||
def get_collections(self):
|
|
||||||
return self.get_party_total("Customer", "credit", self.meta.get_label("collections"))
|
|
||||||
|
|
||||||
def get_payments(self):
|
|
||||||
return self.get_party_total("Supplier", "debit", self.meta.get_label("payments"))
|
|
||||||
|
|
||||||
def get_party_total(self, party_type, gle_field, label):
|
|
||||||
import re
|
|
||||||
party_list = frappe.db.sql_list("select name from `tab{0}`".format(party_type))
|
|
||||||
|
|
||||||
# account is "Bank" or "Cash"
|
|
||||||
bc_accounts = [esc(a["name"], "()|") for a in self.get_accounts()
|
|
||||||
if a["account_type"] in ["Bank", "Cash"]]
|
|
||||||
bc_regex = re.compile("""(%s)""" % "|".join(bc_accounts))
|
|
||||||
|
|
||||||
total = 0
|
|
||||||
for gle in self.get_gl_entries(self.from_date, self.to_date):
|
|
||||||
# check that its made against a bank or cash account
|
|
||||||
if gle["party_type"]==party_type and gle["party"] in party_list and gle["against"] and \
|
|
||||||
bc_regex.findall(gle["against"]):
|
|
||||||
val = gle["debit"] - gle["credit"]
|
|
||||||
total += (gle_field=="debit" and 1 or -1) * val
|
|
||||||
|
|
||||||
return total, self.get_html(label, self.currency, fmt_money(total))
|
|
||||||
|
|
||||||
def get_invoiced_amount(self):
|
|
||||||
# aka receivables
|
|
||||||
return self.get_booked_total("Customer", "debit", self.meta.get_label("invoiced_amount"))
|
|
||||||
|
|
||||||
def get_payables(self):
|
|
||||||
return self.get_booked_total("Supplier", "credit", self.meta.get_label("payables"))
|
|
||||||
|
|
||||||
def get_booked_total(self, party_type, gle_field, label):
|
|
||||||
party_list = frappe.db.sql_list("select name from `tab{0}`".format(party_type))
|
|
||||||
|
|
||||||
total = 0
|
|
||||||
for gle in self.get_gl_entries(self.from_date, self.to_date):
|
|
||||||
if gle["party_type"]==party_type and gle["party"] in party_list:
|
|
||||||
total += gle[gle_field]
|
|
||||||
|
|
||||||
return total, self.get_html(label, self.currency, fmt_money(total))
|
|
||||||
|
|
||||||
def get_new_leads(self):
|
|
||||||
return self.get_new_count("Lead", self.meta.get_label("new_leads"))
|
|
||||||
|
|
||||||
def get_new_enquiries(self):
|
|
||||||
return self.get_new_count("Opportunity", self.meta.get_label("new_enquiries"), docstatus=1,
|
|
||||||
date_field="transaction_date")
|
|
||||||
|
|
||||||
def get_new_quotations(self):
|
|
||||||
return self.get_new_sum("Quotation", self.meta.get_label("new_quotations"), "base_grand_total",
|
|
||||||
date_field="transaction_date")
|
|
||||||
|
|
||||||
def get_new_sales_orders(self):
|
|
||||||
return self.get_new_sum("Sales Order", self.meta.get_label("new_sales_orders"), "base_grand_total",
|
|
||||||
date_field="transaction_date")
|
|
||||||
|
|
||||||
def get_new_delivery_notes(self):
|
|
||||||
return self.get_new_sum("Delivery Note", self.meta.get_label("new_delivery_notes"), "base_grand_total",
|
|
||||||
date_field="posting_date")
|
|
||||||
|
|
||||||
def get_new_purchase_requests(self):
|
|
||||||
return self.get_new_count("Material Request", self.meta.get_label("new_purchase_requests"), docstatus=1,
|
|
||||||
date_field="transaction_date")
|
|
||||||
|
|
||||||
def get_new_supplier_quotations(self):
|
|
||||||
return self.get_new_sum("Supplier Quotation", self.meta.get_label("new_supplier_quotations"),
|
|
||||||
"base_grand_total", date_field="transaction_date")
|
|
||||||
|
|
||||||
def get_new_purchase_orders(self):
|
|
||||||
return self.get_new_sum("Purchase Order", self.meta.get_label("new_purchase_orders"),
|
|
||||||
"base_grand_total", date_field="transaction_date")
|
|
||||||
|
|
||||||
def get_new_purchase_receipts(self):
|
|
||||||
return self.get_new_sum("Purchase Receipt", self.meta.get_label("new_purchase_receipts"),
|
|
||||||
"base_grand_total", date_field="posting_date")
|
|
||||||
|
|
||||||
def get_new_stock_entries(self):
|
|
||||||
return self.get_new_sum("Stock Entry", self.meta.get_label("new_stock_entries"), "total_amount",
|
|
||||||
date_field="posting_date")
|
|
||||||
|
|
||||||
def get_new_support_tickets(self):
|
|
||||||
return self.get_new_count("Issue", self.meta.get_label("new_support_tickets"),
|
|
||||||
filter_by_company=False)
|
|
||||||
|
|
||||||
def get_new_communications(self):
|
|
||||||
return self.get_new_count("Communication", self.meta.get_label("new_communications"),
|
|
||||||
filter_by_company=False)
|
|
||||||
|
|
||||||
def get_new_projects(self):
|
|
||||||
return self.get_new_count("Project", self.meta.get_label("new_projects"),
|
|
||||||
filter_by_company=False)
|
|
||||||
|
|
||||||
def get_calendar_events(self, user_id):
|
|
||||||
from frappe.desk.doctype.event.event import get_events
|
from frappe.desk.doctype.event.event import get_events
|
||||||
events = get_events(self.future_from_date.strftime("%Y-%m-%d"), self.future_to_date.strftime("%Y-%m-%d"))
|
events = get_events(self.future_from_date.strftime("%Y-%m-%d"),
|
||||||
|
self.future_to_date.strftime("%Y-%m-%d")) or []
|
||||||
|
|
||||||
html = ""
|
for i, e in enumerate(events):
|
||||||
if events:
|
e.starts_on_label = format_time(e.starts_on)
|
||||||
for i, e in enumerate(events):
|
e.ends_on_label = format_time(e.ends_on)
|
||||||
if i>=10:
|
e.date = formatdate(e.starts)
|
||||||
break
|
e.link = get_url_to_form("Event", e.name)
|
||||||
if e.all_day:
|
|
||||||
html += """<li style='line-height: 200%%'>%s [%s (%s)]</li>""" % \
|
|
||||||
(e.subject, datetime_in_user_format(e.starts_on), _("All Day"))
|
|
||||||
else:
|
|
||||||
html += "<li style='line-height: 200%%'>%s [%s - %s]</li>" % \
|
|
||||||
(e.subject, datetime_in_user_format(e.starts_on), datetime_in_user_format(e.ends_on))
|
|
||||||
|
|
||||||
if html:
|
return events
|
||||||
return 1, "<h4>" + _("Upcoming Calendar Events (max 10)") + ":</h4><ul>" + html + "</ul><hr>"
|
|
||||||
else:
|
def get_todo_list(self, user_id=None):
|
||||||
return 0, "<p>" + _("Calendar Events") + "</p>"
|
"""Get to-do list"""
|
||||||
|
if not user_id:
|
||||||
|
user_id = frappe.session.user
|
||||||
|
|
||||||
def get_todo_list(self, user_id):
|
|
||||||
todo_list = frappe.db.sql("""select *
|
todo_list = frappe.db.sql("""select *
|
||||||
from `tabToDo` where (owner=%s or assigned_by=%s) and status="Open"
|
from `tabToDo` where (owner=%s or assigned_by=%s) and status="Open"
|
||||||
order by field(priority, 'High', 'Medium', 'Low') asc, date asc""",
|
order by field(priority, 'High', 'Medium', 'Low') asc, date asc""",
|
||||||
(user_id, user_id), as_dict=True)
|
(user_id, user_id), as_dict=True)
|
||||||
|
|
||||||
html = ""
|
for t in todo_list:
|
||||||
if todo_list:
|
t.link = get_url_to_form("ToDo", t.name)
|
||||||
for i, todo in enumerate([todo for todo in todo_list if not todo.checked]):
|
|
||||||
if i>= 10:
|
|
||||||
break
|
|
||||||
if not todo.description and todo.reference_type:
|
|
||||||
todo.description = "%s: %s - %s %s" % \
|
|
||||||
(todo.reference_type, get_url_to_form(todo.reference_type, todo.reference_name),
|
|
||||||
_("assigned by"), get_fullname(todo.assigned_by))
|
|
||||||
|
|
||||||
html += "<li style='line-height: 200%%'>%s [%s]</li>" % (todo.description, todo.priority)
|
return todo_list
|
||||||
|
|
||||||
if html:
|
def set_accounting_cards(self, context):
|
||||||
return 1, "<h4>To Do (max 10):</h4><ul>" + html + "</ul><hr>"
|
"""Create accounting cards if checked"""
|
||||||
else:
|
|
||||||
return 0, "<p>To Do</p>"
|
|
||||||
|
|
||||||
def get_new_count(self, doctype, label, docstatus=0, filter_by_company=True, date_field="creation"):
|
context.cards = []
|
||||||
if filter_by_company:
|
for key in ("income", "expenses_booked", "income_year_to_date", "expense_year_to_date",
|
||||||
company_condition = """and company="%s" """ % self.company.replace('"', '\"')
|
"invoiced_amount", "payables", "bank_balance"):
|
||||||
else:
|
if self.get(key):
|
||||||
company_condition = ""
|
card = frappe._dict(getattr(self, "get_" + key)())
|
||||||
|
|
||||||
count = frappe.db.sql("""select count(*) from `tab{doctype}`
|
# format values
|
||||||
where ifnull(`docstatus`, 0)=%s {company_condition} and
|
if card.last_value:
|
||||||
date(`{date_field}`)>=%s and date({date_field})<=%s""".format(doctype=doctype,
|
card.diff = int(flt(card.value - card.last_value) / card.last_value * 100)
|
||||||
company_condition=company_condition, date_field=date_field),
|
if card.diff < 0:
|
||||||
(docstatus, self.from_date, self.to_date))
|
card.diff = str(card.diff)
|
||||||
|
card.gain = False
|
||||||
|
else:
|
||||||
|
card.diff = "+" + str(card.diff)
|
||||||
|
card.gain = True
|
||||||
|
|
||||||
count = count and count[0][0] or 0
|
card.last_value = self.fmt_money(card.last_value)
|
||||||
|
|
||||||
return count, self.get_html(label, None, count)
|
card.value = self.fmt_money(card.value)
|
||||||
|
|
||||||
def get_new_sum(self, doctype, label, sum_field, date_field="creation"):
|
context.cards.append(card)
|
||||||
count_sum = frappe.db.sql("""select count(*), sum(ifnull(`{sum_field}`, 0))
|
|
||||||
from `tab{doctype}` where docstatus=1 and company = %s and
|
|
||||||
date(`{date_field}`)>=%s and date(`{date_field}`)<=%s""".format(sum_field=sum_field,
|
|
||||||
date_field=date_field, doctype=doctype), (self.company, self.from_date, self.to_date))
|
|
||||||
|
|
||||||
count, total = count_sum and count_sum[0] or (0, 0)
|
def get_income(self):
|
||||||
|
"""Get income for given period"""
|
||||||
|
income, past_income = self.get_period_amounts(self.get_root_type_accounts("income"))
|
||||||
|
|
||||||
return count, self.get_html(label, self.currency,
|
return {
|
||||||
"%s - (%s)" % (fmt_money(total), cstr(count)))
|
"label": self.meta.get_label("income"),
|
||||||
|
"value": income,
|
||||||
|
"last_value": past_income
|
||||||
|
}
|
||||||
|
|
||||||
def get_html(self, label, currency, value, style=None):
|
def get_income_year_to_date(self):
|
||||||
"""get html output"""
|
"""Get income to date"""
|
||||||
return row_template % {
|
return self.get_year_to_date_balance("income")
|
||||||
"style": style or "",
|
|
||||||
"label": label,
|
|
||||||
"currency": currency and (currency+" ") or "",
|
|
||||||
"value": value
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_gl_entries(self, from_date=None, to_date=None):
|
def get_expense_year_to_date(self):
|
||||||
"""get valid GL Entries filtered by company and posting date"""
|
"""Get income to date"""
|
||||||
if from_date==self.from_date and to_date==self.to_date and \
|
return self.get_year_to_date_balance("expense")
|
||||||
hasattr(self, "gl_entries"):
|
|
||||||
return self.gl_entries
|
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select `account`, `party_type`, `party`,
|
def get_year_to_date_balance(self, root_type):
|
||||||
ifnull(credit, 0) as credit, ifnull(debit, 0) as debit, `against`
|
"""Get income to date"""
|
||||||
from `tabGL Entry`
|
balance = 0.0
|
||||||
where company=%s
|
|
||||||
and posting_date <= %s %s""" % ("%s", "%s",
|
|
||||||
from_date and "and posting_date>='%s'" % from_date or ""),
|
|
||||||
(self.company, to_date or self.to_date), as_dict=1)
|
|
||||||
|
|
||||||
# cache if it is the normal cases
|
for account in self.get_root_type_accounts(root_type):
|
||||||
if from_date==self.from_date and to_date==self.to_date:
|
balance += get_balance_on(account, date = self.future_to_date)
|
||||||
self.gl_entries = gl_entries
|
|
||||||
|
|
||||||
return gl_entries
|
return {
|
||||||
|
"label": self.meta.get_label(root_type + "_year_to_date"),
|
||||||
|
"value": balance
|
||||||
|
}
|
||||||
|
|
||||||
def get_accounts(self):
|
def get_bank_balance(self):
|
||||||
if not hasattr(self, "accounts"):
|
# account is of type "Bank" or "Cash"
|
||||||
self.accounts = frappe.db.sql("""select name, account_type, account_name, root_type
|
return self.get_type_balance('bank_balance', 'Bank')
|
||||||
from `tabAccount` where company=%s and docstatus < 2
|
|
||||||
and is_group = 0 order by lft""",
|
def get_payables(self):
|
||||||
(self.company,), as_dict=1)
|
return self.get_type_balance('payables', 'Payable')
|
||||||
return self.accounts
|
|
||||||
|
def get_invoiced_amount(self):
|
||||||
|
return self.get_type_balance('invoiced_amount', 'Receivable')
|
||||||
|
|
||||||
|
def get_expenses_booked(self):
|
||||||
|
expense, past_expense = self.get_period_amounts(self.get_root_type_accounts("expense"))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"label": self.meta.get_label("expenses_booked"),
|
||||||
|
"value": expense,
|
||||||
|
"last_value": past_expense
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_period_amounts(self, accounts):
|
||||||
|
"""Get amounts for current and past periods"""
|
||||||
|
balance = past_balance = 0.0
|
||||||
|
for account in accounts:
|
||||||
|
balance += (get_balance_on(account, date = self.future_to_date)
|
||||||
|
- get_balance_on(account, date = self.future_from_date))
|
||||||
|
|
||||||
|
past_balance += (get_balance_on(account, date = self.past_to_date)
|
||||||
|
- get_balance_on(account, date = self.past_from_date))
|
||||||
|
|
||||||
|
return balance, past_balance
|
||||||
|
|
||||||
|
def get_type_balance(self, fieldname, account_type):
|
||||||
|
accounts = [d.name for d in \
|
||||||
|
frappe.db.get_all("Account", filters={"account_type": account_type,
|
||||||
|
"company": self.company, "is_group": 0})]
|
||||||
|
|
||||||
|
balance = prev_balance = 0.0
|
||||||
|
for account in accounts:
|
||||||
|
balance += get_balance_on(account, date=self.future_from_date)
|
||||||
|
prev_balance += get_balance_on(account, date=self.past_from_date)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': self.meta.get_label(fieldname),
|
||||||
|
'value': balance,
|
||||||
|
'last_value': prev_balance
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_root_type_accounts(self, root_type):
|
||||||
|
if not root_type in self._accounts:
|
||||||
|
self._accounts[root_type] = [d.name for d in \
|
||||||
|
frappe.db.get_all("Account", filters={"root_type": root_type.title(),
|
||||||
|
"company": self.company, "is_group": 0})]
|
||||||
|
return self._accounts[root_type]
|
||||||
|
|
||||||
def get_from_to_date(self):
|
def get_from_to_date(self):
|
||||||
today = now_datetime().date()
|
today = now_datetime().date()
|
||||||
@ -417,25 +280,33 @@ class EmailDigest(Document):
|
|||||||
|
|
||||||
return from_date, to_date
|
return from_date, to_date
|
||||||
|
|
||||||
def get_future_from_to_date(self):
|
def set_dates(self):
|
||||||
today = now_datetime().date()
|
today = now_datetime().date()
|
||||||
|
|
||||||
# decide from date based on email digest frequency
|
# decide from date based on email digest frequency
|
||||||
if self.frequency == "Daily":
|
if self.frequency == "Daily":
|
||||||
# from date, to_date is today
|
# from date, to_date is today
|
||||||
from_date = to_date = today
|
self.future_from_date = self.future_to_date = today
|
||||||
|
self.past_from_date = self.past_to_date = today - relativedelta(days = 1)
|
||||||
|
|
||||||
elif self.frequency == "Weekly":
|
elif self.frequency == "Weekly":
|
||||||
# from date is the current week's monday
|
# from date is the current week's monday
|
||||||
from_date = today - timedelta(days=today.weekday())
|
self.future_from_date = today - relativedelta(days=today.weekday())
|
||||||
|
|
||||||
# to date is the current week's sunday
|
# to date is the current week's sunday
|
||||||
to_date = from_date + timedelta(days=6)
|
self.future_to_date = self.future_from_date + relativedelta(days=6)
|
||||||
|
|
||||||
|
self.past_from_date = self.future_from_date - relativedelta(days=7)
|
||||||
|
self.past_to_date = self.future_to_date - relativedelta(days=7)
|
||||||
else:
|
else:
|
||||||
# from date is the 1st day of the current month
|
# from date is the 1st day of the current month
|
||||||
from_date = today - relativedelta(days=today.day-1)
|
self.future_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
|
# to date is the last day of the current month
|
||||||
|
self.future_to_date = self.future_from_date + relativedelta(days=-1, months=1)
|
||||||
|
|
||||||
|
self.past_from_date = self.future_from_date - relativedelta(month=1)
|
||||||
|
self.past_to_date = self.future_to_date - relativedelta(month=1)
|
||||||
|
|
||||||
def get_next_sending(self):
|
def get_next_sending(self):
|
||||||
from_date, to_date = self.get_from_to_date()
|
from_date, to_date = self.get_from_to_date()
|
||||||
@ -452,25 +323,12 @@ class EmailDigest(Document):
|
|||||||
|
|
||||||
return send_date
|
return send_date
|
||||||
|
|
||||||
def get_open_tickets(self):
|
|
||||||
open_tickets = frappe.db.sql("""select name, subject, modified, raised_by
|
|
||||||
from `tabIssue` where status='Open'
|
|
||||||
order by modified desc limit 10""", as_dict=True)
|
|
||||||
|
|
||||||
if open_tickets:
|
|
||||||
return 1, """<hr><h4>Latest Open Tickets (max 10):</h4>%s""" % \
|
|
||||||
"".join(["<p>%(name)s: %(subject)s <br>by %(raised_by)s on %(modified)s</p>" % \
|
|
||||||
t for t in open_tickets])
|
|
||||||
else:
|
|
||||||
return 0, "No Open Tickets!"
|
|
||||||
|
|
||||||
def get_scheduler_errors(self):
|
|
||||||
import frappe.utils.scheduler
|
|
||||||
return frappe.utils.scheduler.get_error_report(self.from_date, self.to_date)
|
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
self.get_next_sending()
|
self.get_next_sending()
|
||||||
|
|
||||||
|
def fmt_money(self, value):
|
||||||
|
return fmt_money(value, currency = self.currency)
|
||||||
|
|
||||||
def send():
|
def send():
|
||||||
now_date = now_datetime().date()
|
now_date = now_datetime().date()
|
||||||
|
|
||||||
@ -479,3 +337,7 @@ def send():
|
|||||||
ed_obj = frappe.get_doc('Email Digest', ed[0])
|
ed_obj = frappe.get_doc('Email Digest', ed[0])
|
||||||
if (now_date == ed_obj.get_next_sending()):
|
if (now_date == ed_obj.get_next_sending()):
|
||||||
ed_obj.send()
|
ed_obj.send()
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_digest_msg(name):
|
||||||
|
return frappe.get_doc("Email Digest", name).get_msg_html()
|
||||||
|
111
erpnext/setup/doctype/email_digest/templates/default.html
Normal file
111
erpnext/setup/doctype/email_digest/templates/default.html
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
{% macro show_card(card) %}
|
||||||
|
<div style="width: 50%; float:left; min-height: 120px; padding-top: 20px;">
|
||||||
|
<h6 style="color: {{ text_muted }}">{{ card.label }}</h6>
|
||||||
|
<h4>{{ card.value }}</h4>
|
||||||
|
{% if card.diff %}
|
||||||
|
<p style="color: {{ text_muted }}">{{ card.diff }}%</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
<div style="max-width: 500px; margin: auto; padding: 20px 0 40px 0">
|
||||||
|
|
||||||
|
{% if cards %}
|
||||||
|
<h1 style="{{ h1 }}">{{ title }}</h1>
|
||||||
|
<h4 style="font-weight: normal; color: {{ text_muted }}; margin-top: 7px">
|
||||||
|
<p>{% if frequency == "Daily "%}
|
||||||
|
{{ frappe.format_date(future_from_date) }}
|
||||||
|
{% else %}
|
||||||
|
{{ frappe.format_date(future_from_date) }} - {{ frappe.format_date(future_to_date) }}
|
||||||
|
{% endif %}</p>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<!-- cards -->
|
||||||
|
<div>
|
||||||
|
{% for card in cards %}
|
||||||
|
{{ show_card(card) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
<h1 style="{{ h1 }}">{{ _("Pending Activities") }}</h1>
|
||||||
|
|
||||||
|
<!-- events -->
|
||||||
|
{% if events %}
|
||||||
|
<h4 style="{{ section_head }}">{{ _("Upcoming Events") }}</h4>
|
||||||
|
<div>
|
||||||
|
{% for e in events %}
|
||||||
|
{% if loop.index==1 or events[loop.index-1].date != e.date %}
|
||||||
|
<p style="margin-top: 25px;"><b>{{ e.date }}</b></p>
|
||||||
|
{% endif %}
|
||||||
|
<div style="{{ line_item }}">
|
||||||
|
<table style="width: 100%;">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ e.link }}">{{ e.subject }}</a>
|
||||||
|
</td>
|
||||||
|
<td style="width: 40%; text-align: right">
|
||||||
|
<span style="{{ label_css }}">
|
||||||
|
{% if e.all_day %}
|
||||||
|
{{ _("All Day") }}
|
||||||
|
{% else %}
|
||||||
|
{{ e.starts_on_label }} - {{ e.ends_on_label }}
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- todo list -->
|
||||||
|
{% if todo_list %}
|
||||||
|
<h4 style="{{ section_head }}">{{ _("To Do List") }}</h4>
|
||||||
|
<div>
|
||||||
|
{% for t in todo_list %}
|
||||||
|
<div style="{{ line_item }}">
|
||||||
|
<table style="width: 100%;">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ t.link }}">{{ t.description }}</a>
|
||||||
|
</td>
|
||||||
|
<td style="width: 25%; text-align: right">
|
||||||
|
<span style="{{ label_css }}">
|
||||||
|
{{ _(t.status) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- notifications -->
|
||||||
|
{% if notifications %}
|
||||||
|
<h4 style="{{ section_head }}">{{ _("Open Notifications") }}</h4>
|
||||||
|
<div>
|
||||||
|
{% for n in notifications %}
|
||||||
|
<div style="{{ line_item }}">
|
||||||
|
<table style="width: 100%;">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="n.link">{{ n.key }}</a>
|
||||||
|
</td>
|
||||||
|
<td style="width: 25%; text-align: right">
|
||||||
|
<span style="{{ label_css }}">
|
||||||
|
{{ n.value }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
12
erpnext/setup/doctype/email_digest/test_email_digest.py
Normal file
12
erpnext/setup/doctype/email_digest/test_email_digest.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# test_records = frappe.get_test_records('Email Digest')
|
||||||
|
|
||||||
|
class TestEmailDigest(unittest.TestCase):
|
||||||
|
pass
|
Loading…
x
Reference in New Issue
Block a user