diff --git a/erpnext/setup/doctype/email_digest/email_digest.json b/erpnext/setup/doctype/email_digest/email_digest.json
index 12f275c75d..da95b259e2 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.json
+++ b/erpnext/setup/doctype/email_digest/email_digest.json
@@ -4,7 +4,7 @@
"allow_rename": 0,
"autoname": "Prompt",
"beta": 0,
- "creation": "2013-02-21 14:15:31",
+ "creation": "2018-09-16 22:00:00",
"custom": 0,
"description": "Send regular summary reports via Email.",
"docstatus": 0,
@@ -563,6 +563,90 @@
"set_only_once": 0,
"unique": 0
},
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "work_in_progress",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Work in Progress",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "sales_orders_to_bill",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Sales Orders to Bill",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "purchase_orders_to_bill",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purchase Orders to Bill",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
{
"allow_on_submit": 0,
"bold": 0,
@@ -646,34 +730,6 @@
"set_only_once": 0,
"unique": 0
},
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "pending_sales_orders",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Pending Sales Orders",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
{
"allow_on_submit": 0,
"bold": 0,
@@ -686,7 +742,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "in_standard_filter": 0,
+ "in_standard_filter": 0,
"label": "New Purchase Orders",
"length": 0,
"no_copy": 0,
@@ -707,15 +763,15 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "pending_purchase_orders",
+ "fieldname": "sales_orders_to_deliver",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Pending Purchase Orders",
+ "in_standard_filter": 0,
+ "label": "Sales Orders to Deliver",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -730,6 +786,34 @@
"set_only_once": 0,
"unique": 0
},
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "purchase_orders_to_receive",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purchase Orders to Receive",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
{
"allow_on_submit": 0,
"bold": 0,
@@ -798,8 +882,8 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Pending Quotations",
+ "in_standard_filter": 0,
+ "label": "Open Quotations",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -869,6 +953,34 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "purchase_orders_items_overdue",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purchase Orders Items Overdue",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
},
{
"allow_on_submit": 0,
@@ -1079,7 +1191,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-11-07 05:10:32.190134",
+ "modified": "2018-09-16 22:00:00.000000",
"modified_by": "Administrator",
"module": "Setup",
"name": "Email Digest",
diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py
index e2189a14b7..d309e88523 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.py
+++ b/erpnext/setup/doctype/email_digest/email_digest.py
@@ -96,7 +96,13 @@ class EmailDigest(Document):
quote = get_random_quote()
context.quote = {"text": quote[0], "author": quote[1]}
- if not (context.events or context.todo_list or context.notifications or context.cards):
+ if self.get("purchase_orders_items_overdue"):
+ context.purchase_order_list, context.purchase_orders_items_overdue_list = self.get_purchase_orders_items_overdue_list()
+ if not context.purchase_order_list:
+ frappe.throw(_("No items to be received are overdue"))
+
+ if not (context.events or context.todo_list or context.notifications or context.cards
+ or context.purchase_orders_items_overdue_list):
return None
frappe.flags.ignore_account_permission = False
@@ -230,9 +236,10 @@ class EmailDigest(Document):
cache = frappe.cache()
context.cards = []
- for key in ("income", "expenses_booked", "income_year_to_date","expense_year_to_date",
- "new_quotations","pending_quotations","sales_order","purchase_order","pending_sales_orders","pending_purchase_orders",
- "invoiced_amount", "payables", "bank_balance", "credit_balance"):
+ for key in ("income", "expenses_booked", "income_year_to_date", "expense_year_to_date",
+ "bank_balance", "credit_balance", "invoiced_amount", "payables",
+ "sales_orders_to_bill", "purchase_orders_to_bill", "sales_order", "purchase_order",
+ "sales_orders_to_deliver", "purchase_orders_to_receive", "new_quotations", "pending_quotations"):
if self.get(key):
cache_key = "email_digest:card:{0}:{1}:{2}:{3}".format(self.company, self.frequency, key, self.from_date)
card = cache.get(cache_key)
@@ -346,6 +353,62 @@ class EmailDigest(Document):
return balance, past_balance, count
+ def get_sales_orders_to_bill(self):
+ """Get value not billed"""
+
+ value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0),
+ count(*) from `tabSales Order`
+ where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed"
+ and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+
+ return {
+ "label": self.meta.get_label("sales_orders_to_bill"),
+ "value": value,
+ "count": count
+ }
+
+ def get_sales_orders_to_deliver(self):
+ """Get value not delivered"""
+
+ value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_delivered/100)),0),
+ count(*) from `tabSales Order`
+ where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered"
+ and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+
+ return {
+ "label": self.meta.get_label("sales_orders_to_deliver"),
+ "value": value,
+ "count": count
+ }
+
+ def get_purchase_orders_to_receive(self):
+ """Get value not received"""
+
+ value, count = frappe.db.sql("""select ifnull((sum(grand_total))-(sum(grand_total*per_received/100)),0),
+ count(*) from `tabPurchase Order`
+ where (transaction_date <= %(to_date)s) and per_received < 100
+ and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+
+ return {
+ "label": self.meta.get_label("purchase_orders_to_receive"),
+ "value": value,
+ "count": count
+ }
+
+ def get_purchase_orders_to_bill(self):
+ """Get purchase not billed"""
+
+ value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0),
+ count(*) from `tabPurchase Order`
+ where (transaction_date <= %(to_date)s) and per_billed < 100
+ and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+
+ return {
+ "label": self.meta.get_label("purchase_orders_to_bill"),
+ "value": value,
+ "count": count
+ }
+
def get_type_balance(self, fieldname, account_type, root_type=None):
if root_type:
@@ -529,6 +592,30 @@ class EmailDigest(Document):
else:
return fmt_money(value, currency=self.currency)
+ def get_purchase_orders_items_overdue_list(self):
+ fields_po = "distinct `tabPurchase Order Item`.parent as po"
+ fields_poi = "`tabPurchase Order Item`.parent, `tabPurchase Order Item`.schedule_date, item_code," \
+ "received_qty, qty - received_qty as missing_qty, rate, amount"
+
+ sql_po = """select {fields} from `tabPurchase Order Item`
+ left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent
+ where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and curdate() > `tabPurchase Order Item`.schedule_date
+ and received_qty < qty order by `tabPurchase Order Item`.parent DESC,
+ `tabPurchase Order Item`.schedule_date DESC""".format(fields=fields_po)
+
+ sql_poi = """select {fields} from `tabPurchase Order Item`
+ left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent
+ where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and curdate() > `tabPurchase Order Item`.schedule_date
+ and received_qty < qty order by `tabPurchase Order Item`.idx""".format(fields=fields_poi)
+ purchase_order_list = frappe.db.sql(sql_po, as_dict=True)
+ purchase_order_items_overdue_list = frappe.db.sql(sql_poi, as_dict=True)
+
+ for t in purchase_order_items_overdue_list:
+ t.link = get_url_to_form("Purchase Order", t.parent)
+ t.rate = fmt_money(t.rate, 2, t.currency)
+ t.amount = fmt_money(t.amount, 2, t.currency)
+ return purchase_order_list, purchase_order_items_overdue_list
+
def send():
now_date = now_datetime().date()
diff --git a/erpnext/setup/doctype/email_digest/templates/default.html b/erpnext/setup/doctype/email_digest/templates/default.html
index 5a657d26a3..4ee4b0ff16 100644
--- a/erpnext/setup/doctype/email_digest/templates/default.html
+++ b/erpnext/setup/doctype/email_digest/templates/default.html
@@ -1,6 +1,6 @@
{% macro show_card(card) %}
-
-
{{ _(card.label) }}
+
+
{{ card.label }}
{% if card.count %}
({{ card.count }})
{% endif %}
@@ -180,5 +180,80 @@
{% endif %}
-
+
+
+{% if purchase_orders_items_overdue_list %}
+{{ _("Purchase Order Items not received on time") }}
+
+
+
+
+
+
+ Item Code
+ |
+
+ Quantity
+ |
+
+ Rate
+ |
+
+ Amount
+ |
+
+
+
+
+
+ {% for po in purchase_order_list %}
+
+
+
+
+ {{ po.po }}
+ |
+
+
+
+ {% for t in purchase_orders_items_overdue_list %}
+ {% if t.parent == po.po %}
+
+
+
+
+ {{ _(t.item_code) }}
+ |
+
+
+ {{ t.missing_qty }}
+
+ |
+
+
+ {{ t.rate }}
+
+ |
+
+
+ {{ t.amount }}
+
+ |
+
+
+
+ {% endif %}
+ {% endfor %}
+ |
+
+
+
+ {% endfor %}
+
+
+
+
Please take necessary action
+
+{% endif %}
+