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
This commit is contained in:
Alchez 2018-09-30 21:38:47 +05:30 committed by Rushabh Mehta
parent 4fd7a4e0d7
commit 6ecb2556b7
17 changed files with 641 additions and 339 deletions

View File

@ -566,3 +566,4 @@ erpnext.patches.v11_0.redesign_healthcare_billing_work_flow
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

View File

@ -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()

View File

@ -55,6 +55,10 @@ def set_default_settings(args):
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")

View File

@ -250,6 +250,12 @@ def install(country=None):
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()

View File

@ -460,6 +460,7 @@ def make_delivery_trip(source_name, target_doc=None):
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)

View File

@ -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) {
}
});

View File

@ -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
}

View File

@ -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

View File

@ -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()
]);
});

View File

@ -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

View File

@ -18,7 +18,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"columns": 2,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
@ -78,6 +78,38 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"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,
@ -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,135 @@
"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,
"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": "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,
@ -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,
@ -205,6 +366,38 @@
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 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",

View File

@ -93,12 +93,8 @@ frappe.ui.form.on('Delivery Trip', {
},
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,26 +103,29 @@ frappe.ui.form.on('Delivery Trip', {
});
}
});
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: {
"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
}
});
"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) {
@ -158,6 +157,7 @@ frappe.ui.form.on('Delivery Stop', {
});
}
},
address: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.address) {

View File

@ -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,
@ -531,40 +531,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"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,
@ -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",

View File

@ -10,8 +10,7 @@ import frappe
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 @@ def get_arrival_times(name):
@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,
if delivery_trip.driver:
context.update(frappe.db.get_value("Driver", delivery_trip.driver, "cell_number", as_dict=1))
email_recipients = []
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)
args.update(delivery_stop.as_dict())
args.update(contact_info)
if contact_info and contact_info.email_id:
context.update(stop.as_dict())
context.update(contact_info)
if delivery_stop.delivery_note:
default_print_format = frappe.get_meta('Delivery Note').default_print_format
attachments = frappe.attach_print('Delivery Note',
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,
subject=dispatch_template.subject,
message=frappe.render_template(dispatch_template.response, context),
attachments=get_attachments(stop))
stop.db_set("email_sent_to", contact_info.email_id)
email_recipients.append(contact_info.email_id)
if email_recipients:
frappe.msgprint(_("Email sent to {0}").format(", ".join(email_recipients)))
delivery_trip.db_set("email_notification_sent", True)
else:
frappe.msgprint(_("No contacts with email IDs found."))
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=default_print_format or "Standard")
print_format=dispatch_attachment)
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"])
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)
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.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))
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))
else:
return datetime.timedelta(seconds=td.total_seconds() - remainder)
def format_address(address):
"""Customer Address format """
address = frappe.get_doc('Address', address)
return '{}, {}, {}, {}'.format(address.address_line1, address.city, address.pincode, address.country)
return [attachments]

View File

@ -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>

View File

@ -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", {
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"):