Add Delivery Settings + improve 'Notify Customers' functionality (#15322)
* Add Delivery Settings + improve 'Notify Customers' functionality
* Minor improvements
* Add patch to create a default dispatch notification template
* Fix travis errors
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 8c18d14..0c20dbd 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -566,3 +566,4 @@
erpnext.patches.v10_0.delete_hub_documents # 12-08-2018
erpnext.patches.v11_0.rename_healthcare_fields
erpnext.patches.v11_0.remove_land_unit_icon
+erpnext.patches.v11_0.add_default_dispatch_notification_template
diff --git a/erpnext/patches/v11_0/add_default_dispatch_notification_template.py b/erpnext/patches/v11_0/add_default_dispatch_notification_template.py
new file mode 100644
index 0000000..08006ad
--- /dev/null
+++ b/erpnext/patches/v11_0/add_default_dispatch_notification_template.py
@@ -0,0 +1,25 @@
+import os
+
+import frappe
+from frappe import _
+
+
+def execute():
+ frappe.reload_doc("email", "doctype", "email_template")
+ frappe.reload_doc("stock", "doctype", "delivery_settings")
+
+ if not frappe.db.exists("Email Template", _("Dispatch Notification")):
+ base_path = frappe.get_app_path("erpnext", "stock", "doctype")
+ response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html"))
+
+ frappe.get_doc({
+ "doctype": "Email Template",
+ "name": _("Dispatch Notification"),
+ "response": response,
+ "subject": _("Your order is out for delivery!"),
+ "owner": frappe.session.user,
+ }).insert(ignore_permissions=True)
+
+ delivery_settings = frappe.get_doc("Delivery Settings")
+ delivery_settings.dispatch_template = _("Dispatch Notification")
+ delivery_settings.save()
diff --git a/erpnext/setup/setup_wizard/operations/defaults_setup.py b/erpnext/setup/setup_wizard/operations/defaults_setup.py
index 657905d..ff8dd75 100644
--- a/erpnext/setup/setup_wizard/operations/defaults_setup.py
+++ b/erpnext/setup/setup_wizard/operations/defaults_setup.py
@@ -55,6 +55,10 @@
buying_settings.allow_multiple_items = 1
buying_settings.save()
+ delivery_settings = frappe.get_doc("Delivery Settings")
+ delivery_settings.dispatch_template = _("Dispatch Notification")
+ delivery_settings.save()
+
hr_settings = frappe.get_doc("HR Settings")
hr_settings.emp_created_by = "Naming Series"
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 59e6577..194e0dd 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -250,6 +250,12 @@
records += [{'doctype': 'Email Template', 'name': _("Leave Status Notification"), 'response': response,\
'subject': _("Leave Status Notification"), 'owner': frappe.session.user}]
+ base_path = frappe.get_app_path("erpnext", "stock", "doctype")
+ response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html"))
+
+ records += [{'doctype': 'Email Template', 'name': _("Dispatch Notification"), 'response': response,\
+ 'subject': _("Your order is out for delivery!"), 'owner': frappe.session.user}]
+
# Records for the Supplier Scorecard
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
make_default_records()
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 6e45273..6fec612 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -460,6 +460,7 @@
target_doc.customer_address = source_parent.shipping_address
target_doc.contact = source_parent.contact_person
target_doc.customer_contact = source_parent.contact_display
+ target_doc.grand_total = source_parent.grand_total
# Append unique Delivery Notes in Delivery Trip
delivery_notes.append(target_doc.delivery_note)
diff --git a/erpnext/stock/doctype/delivery_settings/__init__.py b/erpnext/stock/doctype/delivery_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_settings/__init__.py
diff --git a/erpnext/stock/doctype/delivery_settings/delivery_settings.js b/erpnext/stock/doctype/delivery_settings/delivery_settings.js
new file mode 100644
index 0000000..03aa192
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_settings/delivery_settings.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Delivery Settings', {
+ refresh: function(frm) {
+
+ }
+});
diff --git a/erpnext/stock/doctype/delivery_settings/delivery_settings.json b/erpnext/stock/doctype/delivery_settings/delivery_settings.json
new file mode 100644
index 0000000..b70d74d
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_settings/delivery_settings.json
@@ -0,0 +1,194 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-09-04 23:01:34.458550",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "sb_dispatch",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Dispatch Settings",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "dispatch_template",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Dispatch Notification Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Email Template",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "send_with_attachment",
+ "description": "Leave blank to use the standard Delivery Note format",
+ "fieldname": "dispatch_attachment",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Dispatch Notification Attachment",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Print Format",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "send_with_attachment",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Send with Attachment",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 1,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-09-05 00:16:23.569855",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Delivery Settings",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 0,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_settings/delivery_settings.py b/erpnext/stock/doctype/delivery_settings/delivery_settings.py
new file mode 100644
index 0000000..909efda
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_settings/delivery_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class DeliverySettings(Document):
+ pass
diff --git a/erpnext/stock/doctype/delivery_settings/test_delivery_settings.js b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.js
new file mode 100644
index 0000000..22977c0
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Delivery Settings", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Delivery Settings
+ () => frappe.tests.make('Delivery Settings', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py
new file mode 100644
index 0000000..4395d26
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestDeliverySettings(unittest.TestCase):
+ pass
diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.json b/erpnext/stock/doctype/delivery_stop/delivery_stop.json
index 4fe4102..023e34d 100644
--- a/erpnext/stock/doctype/delivery_stop/delivery_stop.json
+++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.json
@@ -18,7 +18,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "columns": 0,
+ "columns": 2,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
@@ -85,6 +85,38 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "lock",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Lock",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"hidden": 0,
@@ -148,7 +180,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "section_break_7",
+ "fieldname": "order_information_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -157,6 +189,71 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
+ "label": "Order Information",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "delivery_note",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Delivery Note",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Delivery Note",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "cb_order",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -179,6 +276,70 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Grand Total",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Contact Information",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "contact",
"fieldtype": "Link",
"hidden": 0,
@@ -186,7 +347,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 1,
+ "in_list_view": 0,
"in_standard_filter": 0,
"label": "Contact Name",
"length": 0,
@@ -212,6 +373,38 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "email_sent_to",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Email sent to",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "column_break_7",
"fieldtype": "Column Break",
"hidden": 0,
@@ -284,6 +477,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
+ "label": "Dispatch Information",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -362,196 +556,6 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_12",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "delivery_note",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Delivery Note",
- "length": 0,
- "no_copy": 1,
- "options": "Delivery Note",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_14",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "notified_by_email",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notified by Email",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_18",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "email_sent_to",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Email sent to",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
}
],
"has_web_view": 0,
@@ -564,7 +568,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-08-21 22:25:53.276548",
+ "modified": "2018-09-05 00:51:55.275009",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Stop",
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.js b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
index f3c0f75..9c31e05 100755
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.js
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
@@ -2,8 +2,8 @@
// For license information, please see license.txt
frappe.ui.form.on('Delivery Trip', {
- setup: function(frm) {
- frm.set_query("driver", function() {
+ setup: function (frm) {
+ frm.set_query("driver", function () {
return {
filters: {
"status": "Active"
@@ -11,7 +11,7 @@
};
});
- frm.set_query("address", "delivery_stops", function(doc, cdt, cdn) {
+ frm.set_query("address", "delivery_stops", function (doc, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.customer) {
return {
@@ -24,7 +24,7 @@
}
})
- frm.set_query("contact", "delivery_stops", function(doc, cdt, cdn) {
+ frm.set_query("contact", "delivery_stops", function (doc, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.customer) {
return {
@@ -45,7 +45,7 @@
});
}
- if (frm.doc.docstatus===0) {
+ if (frm.doc.docstatus === 0) {
frm.add_custom_button(__('Delivery Note'), () => {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_delivery_trip",
@@ -93,12 +93,8 @@
},
notify_customers: function (frm) {
- var owner_email = frm.doc.owner == "Administrator"
- ? frappe.user_info("Administrator").email
- : frm.doc.owner;
-
$.each(frm.doc.delivery_stops || [], function (i, delivery_stop) {
- if (!delivery_stop.delivery_notes) {
+ if (!delivery_stop.delivery_note) {
frappe.msgprint({
"message": __("No Delivery Note selected for Customer {}", [delivery_stop.customer]),
"title": __("Warning"),
@@ -107,34 +103,37 @@
});
}
});
- frappe.confirm(__("Do you want to notify all the customers by email?"), function () {
- frappe.call({
- method: "erpnext.stock.doctype.delivery_trip.delivery_trip.notify_customers",
- args: {
- "docname": frm.doc.name,
- "date": frm.doc.date,
- "driver": frm.doc.driver,
- "vehicle": frm.doc.vehicle,
- "sender_email": owner_email,
- "sender_name": frappe.user.full_name(owner_email),
- "delivery_notification": frm.doc.delivery_notification
- }
- });
- frm.doc.email_notification_sent = true;
- frm.refresh_field('email_notification_sent');
+
+ frappe.db.get_value("Delivery Settings", { name: "Delivery Settings" }, "dispatch_template", (r) => {
+ if (!r.dispatch_template) {
+ frappe.throw(__("Missing email template for dispatch. Please set one in Delivery Settings."));
+ } else {
+ frappe.confirm(__("Do you want to notify all the customers by email?"), function () {
+ frappe.call({
+ method: "erpnext.stock.doctype.delivery_trip.delivery_trip.notify_customers",
+ args: {
+ "delivery_trip": frm.doc.name
+ },
+ callback: function (r) {
+ if (!r.exc) {
+ frm.doc.email_notification_sent = true;
+ frm.refresh_field('email_notification_sent');
+ }
+ }
+ });
+ });
+ }
});
}
});
-
-
frappe.ui.form.on('Delivery Stop', {
customer: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
- if(row.customer) {
+ if (row.customer) {
frappe.call({
method: "erpnext.stock.doctype.delivery_trip.delivery_trip.get_contact_and_address",
- args: {"name": row.customer},
+ args: { "name": row.customer },
callback: function (r) {
if (r.message) {
if (r.message["shipping_address"]) {
@@ -158,12 +157,13 @@
});
}
},
+
address: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
- if(row.address) {
+ if (row.address) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_address_display",
- args: {"address_dict": row.address},
+ args: { "address_dict": row.address },
callback: function (r) {
if (r.message) {
frappe.model.set_value(cdt, cdn, "customer_address", r.message);
@@ -177,10 +177,10 @@
contact: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
- if(row.contact) {
+ if (row.contact) {
frappe.call({
method: "erpnext.stock.doctype.delivery_trip.delivery_trip.get_contact_display",
- args: {"contact": row.contact},
+ args: { "contact": row.contact },
callback: function (r) {
if (r.message) {
frappe.model.set_value(cdt, cdn, "customer_contact", r.message);
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.json b/erpnext/stock/doctype/delivery_trip/delivery_trip.json
index 364bc6b..3cb19af 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.json
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.json
@@ -114,7 +114,7 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
@@ -437,7 +437,7 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 1,
+ "allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
@@ -507,7 +507,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "section_break_13",
+ "fieldname": "section_break_15",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -538,40 +538,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "",
- "fieldname": "delivery_notification",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Delivery Notification",
- "length": 0,
- "no_copy": 0,
- "options": "Email Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -608,7 +574,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-08-30 02:31:49.400138",
+ "modified": "2018-09-05 01:20:34.165834",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Trip",
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index 5f291c3..e932b14 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -10,8 +10,7 @@
from frappe import _
from frappe.contacts.doctype.address.address import get_address_display
from frappe.model.document import Document
-from frappe.utils import cstr, get_datetime, getdate, get_link_to_form
-from frappe.utils.user import get_user_fullname
+from frappe.utils import get_datetime, get_link_to_form
class DeliveryTrip(Document):
@@ -169,59 +168,50 @@
@frappe.whitelist()
-def notify_customers(docname, date, driver, vehicle, sender_email, delivery_notification):
- sender_name = get_user_fullname(sender_email)
- attachments = []
+def notify_customers(delivery_trip):
+ delivery_trip = frappe.get_doc("Delivery Trip", delivery_trip)
- parent_doc = frappe.get_doc('Delivery Trip', docname)
- args = parent_doc.as_dict()
+ context = delivery_trip.as_dict()
- for delivery_stop in parent_doc.delivery_stops:
- contact_info = frappe.db.get_value("Contact", delivery_stop.contact,
- ["first_name", "last_name", "email_id", "gender"], as_dict=1)
+ if delivery_trip.driver:
+ context.update(frappe.db.get_value("Driver", delivery_trip.driver, "cell_number", as_dict=1))
- args.update(delivery_stop.as_dict())
- args.update(contact_info)
+ email_recipients = []
- if delivery_stop.delivery_note:
- default_print_format = frappe.get_meta('Delivery Note').default_print_format
- attachments = frappe.attach_print('Delivery Note',
- delivery_stop.delivery_note,
- file_name="Delivery Note",
- print_format=default_print_format or "Standard")
+ for stop in delivery_trip.delivery_stops:
+ contact_info = frappe.db.get_value("Contact", stop.contact,
+ ["first_name", "last_name", "email_id", "gender"], as_dict=1)
- if not delivery_stop.notified_by_email and contact_info.email_id:
- driver_info = frappe.db.get_value("Driver", driver, ["full_name", "cell_number"], as_dict=1)
- sender_designation = frappe.db.get_value("Employee", sender_email, ["designation"])
+ if contact_info and contact_info.email_id:
+ context.update(stop.as_dict())
+ context.update(contact_info)
- estimated_arrival = cstr(delivery_stop.estimated_arrival)[:-3]
- email_template = frappe.get_doc("Email Template", delivery_notification)
- message = frappe.render_template(email_template.response, args)
+ dispatch_template_name = frappe.db.get_single_value("Delivery Settings", "dispatch_template")
+ dispatch_template = frappe.get_doc("Email Template", dispatch_template_name)
- frappe.sendmail(
- recipients=contact_info.email_id,
- sender=sender_email,
- message=message,
- attachments=attachments,
- subject=_(email_template.subject).format(getdate(date).strftime('%d.%m.%y'),
- estimated_arrival))
+ frappe.sendmail(recipients=contact_info.email_id,
+ subject=dispatch_template.subject,
+ message=frappe.render_template(dispatch_template.response, context),
+ attachments=get_attachments(stop))
- frappe.db.set_value("Delivery Stop", delivery_stop.name, "notified_by_email", 1)
- frappe.db.set_value("Delivery Stop", delivery_stop.name,
- "email_sent_to", contact_info.email_id)
- frappe.msgprint(_("Email sent to {0}").format(contact_info.email_id))
+ stop.db_set("email_sent_to", contact_info.email_id)
+ email_recipients.append(contact_info.email_id)
-def round_timedelta(td, period):
- """Round timedelta"""
- period_seconds = period.total_seconds()
- half_period_seconds = period_seconds / 2
- remainder = td.total_seconds() % period_seconds
- if remainder >= half_period_seconds:
- return datetime.timedelta(seconds=td.total_seconds() + (period_seconds - remainder))
+ if email_recipients:
+ frappe.msgprint(_("Email sent to {0}").format(", ".join(email_recipients)))
+ delivery_trip.db_set("email_notification_sent", True)
else:
- return datetime.timedelta(seconds=td.total_seconds() - remainder)
+ frappe.msgprint(_("No contacts with email IDs found."))
-def format_address(address):
- """Customer Address format """
- address = frappe.get_doc('Address', address)
- return '{}, {}, {}, {}'.format(address.address_line1, address.city, address.pincode, address.country)
+
+def get_attachments(delivery_stop):
+ if not (frappe.db.get_single_value("Delivery Settings", "send_with_attachment") and delivery_stop.delivery_note):
+ return []
+
+ dispatch_attachment = frappe.db.get_single_value("Delivery Settings", "dispatch_attachment")
+ attachments = frappe.attach_print("Delivery Note",
+ delivery_stop.delivery_note,
+ file_name="Delivery Note",
+ print_format=dispatch_attachment)
+
+ return [attachments]
diff --git a/erpnext/stock/doctype/delivery_trip/dispatch_notification_template.html b/erpnext/stock/doctype/delivery_trip/dispatch_notification_template.html
new file mode 100644
index 0000000..90a5c50
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_trip/dispatch_notification_template.html
@@ -0,0 +1,50 @@
+<h1>Dispatch Notification</h1>
+<h3>Details:</h3>
+<table class="table table-bordered small" style="max-width: 500px;">
+ <tbody>
+ <tr>
+ <td>Customer's Name</td>
+ <td>{{ customer }}</td>
+ </tr>
+ <tr>
+ <td>Contact's Name</td>
+ <td>{{ first_name }} {{ last_name }}</td>
+ </tr>
+ <tr>
+ <td>Address Name</td>
+ <td>{{ address }}</td>
+ </tr>
+ <tr>
+ <td>Address Details</td>
+ <td>{{ customer_address }}</td>
+ </tr>
+ <tr>
+ <td>Order Number</td>
+ <td>{{ delivery_note }}</td>
+ </tr>
+ <tr>
+ <td>Order Total</td>
+ <td>{{ grand_total }}</td>
+ </tr>
+ <tr>
+ <td>Departure Time</td>
+ <td>{{ cstr(departure_time) }}</td>
+ </tr>
+ <tr>
+ <td>Estimated Arrival</td>
+ <td>{{ cstr(estimated_arrival) }}</td>
+ </tr>
+ <tr>
+ <td>Driver's Name</td>
+ <td>{{ driver_name }}</td>
+ </tr>
+ <tr>
+ <td>Driver's Number</td>
+ <td>{{ cell_number }}</td>
+ </tr>
+ <tr>
+ <td>Vehicle Number</td>
+ <td>{{ vehicle }}</td>
+ </tr>
+ </tbody>
+</table>
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
index aad36c1..4f7fcd8 100644
--- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
@@ -3,60 +3,70 @@
# See license.txt
from __future__ import unicode_literals
-import frappe
-import erpnext
import unittest
-from frappe.utils import nowdate, add_days
+
+import erpnext
+import frappe
+from erpnext.stock.doctype.delivery_trip.delivery_trip import get_contact_and_address, notify_customers
from erpnext.tests.utils import create_test_contact_and_address
-from erpnext.stock.doctype.delivery_trip.delivery_trip import notify_customers, get_contact_and_address
+from frappe.utils import add_days, now_datetime
+
class TestDeliveryTrip(unittest.TestCase):
def setUp(self):
create_driver()
create_vehicle()
- create_delivery_notfication()
+ create_delivery_notification()
create_test_contact_and_address()
def test_delivery_trip(self):
contact = get_contact_and_address("_Test Customer")
if not frappe.db.exists("Delivery Trip", "TOUR-00000"):
- delivery_trip = frappe.new_doc("Delivery Trip")
- delivery_trip.company = erpnext.get_default_company()
- delivery_trip.date = add_days(nowdate(), 5)
- delivery_trip.driver = "DRIVER-00001"
- delivery_trip.vehicle = "JB 007"
- delivery_trip.append("delivery_stops", {
- "customer": "_Test Customer",
- "address": contact.shipping_address.parent,
- "contact": contact.contact_person.parent
+ delivery_trip = frappe.get_doc({
+ "doctype": "Delivery Trip",
+ "company": erpnext.get_default_company(),
+ "departure_time": add_days(now_datetime(), 5),
+ "driver": "DRIVER-00001",
+ "vehicle": "JB 007",
+ "delivery_stops": [{
+ "customer": "_Test Customer",
+ "address": contact.shipping_address.parent,
+ "contact": contact.contact_person.parent
+ }]
})
- delivery_trip.delivery_notification = 'Delivery Notification'
delivery_trip.insert()
- sender_email = frappe.db.get_value("User", frappe.session.user, "email")
- notify_customers(docname=delivery_trip.name, date=delivery_trip.date, driver=delivery_trip.driver,
- vehicle=delivery_trip.vehicle,
- sender_email=sender_email, delivery_notification=delivery_trip.delivery_notification)
- self.assertEqual(delivery_trip.get("delivery_stops")[0].notified_by_email, 0)
+ notify_customers(delivery_trip=delivery_trip.name)
+ delivery_trip.load_from_db()
+ self.assertEqual(delivery_trip.email_notification_sent, 1)
+
def create_driver():
if not frappe.db.exists("Driver", "Newton Scmander"):
- driver = frappe.new_doc("Driver")
- driver.full_name = "Newton Scmander"
- driver.cell_number = "98343424242"
- driver.license_number = "B809"
+ driver = frappe.get_doc({
+ "doctype": "Driver",
+ "full_name": "Newton Scmander",
+ "cell_number": "98343424242",
+ "license_number": "B809"
+ })
driver.insert()
-def create_delivery_notfication():
+
+def create_delivery_notification():
if not frappe.db.exists("Email Template", "Delivery Notification"):
- frappe.get_doc({
+ dispatch_template = frappe.get_doc({
'doctype': 'Email Template',
'name': 'Delivery Notification',
'response': 'Test Delivery Trip',
'subject': 'Test Subject',
'owner': frappe.session.user
- }).insert()
+ })
+ dispatch_template.insert()
+
+ delivery_settings = frappe.get_single("Delivery Settings")
+ delivery_settings.dispatch_template = 'Delivery Notification'
+
def create_vehicle():
if not frappe.db.exists("Vehicle", "JB 007"):