diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py index e0207d050d..7c04e67766 100644 --- a/erpnext/config/stock.py +++ b/erpnext/config/stock.py @@ -132,6 +132,16 @@ def get_data(): }, ] }, + { + "label": _("Fulfilment"), + "items": [ + { + "type": "doctype", + "name": "Delivery Trip", + "description": _("Delivery Trip service tours to customers.") + } + ] + }, { "label": _("Tools"), "icon": "fa fa-wrench", diff --git a/erpnext/docs/assets/img/stock/delivery_stops.png b/erpnext/docs/assets/img/stock/delivery_stops.png new file mode 100644 index 0000000000..1811cf3675 Binary files /dev/null and b/erpnext/docs/assets/img/stock/delivery_stops.png differ diff --git a/erpnext/docs/assets/img/stock/delivery_trip.png b/erpnext/docs/assets/img/stock/delivery_trip.png new file mode 100644 index 0000000000..6913542cfa Binary files /dev/null and b/erpnext/docs/assets/img/stock/delivery_trip.png differ diff --git a/erpnext/docs/user/manual/en/stock/delivery-trip.md b/erpnext/docs/user/manual/en/stock/delivery-trip.md new file mode 100644 index 0000000000..5e0911ad24 --- /dev/null +++ b/erpnext/docs/user/manual/en/stock/delivery-trip.md @@ -0,0 +1,17 @@ +# Delivery Trip + +Delivery Trip is created to record Customer Deliveries in one vehicle. Multiple stops can also be added and Submitted Delivery Note can be tagged per Customer. + +You can make a Delivery directly from: + +> Stock > Delivery Trip > New Delivery Trip + +Delivery + +Delivery + +Delivery Stops + +Delivery + +{next} \ No newline at end of file diff --git a/erpnext/hr/doctype/driver/__init__.py b/erpnext/hr/doctype/driver/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/hr/doctype/driver/driver.js b/erpnext/hr/doctype/driver/driver.js new file mode 100644 index 0000000000..014c4d3058 --- /dev/null +++ b/erpnext/hr/doctype/driver/driver.js @@ -0,0 +1,5 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Driver', { +}); diff --git a/erpnext/hr/doctype/driver/driver.json b/erpnext/hr/doctype/driver/driver.json new file mode 100644 index 0000000000..ccead4e71d --- /dev/null +++ b/erpnext/hr/doctype/driver/driver.json @@ -0,0 +1,528 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "naming_series:", + "beta": 0, + "creation": "2017-10-17 08:21:50.489773", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "naming_series", + "fieldtype": "Select", + "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": "Series", + "length": 0, + "no_copy": 0, + "options": "DRIVER-.#####", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "full_name", + "fieldtype": "Data", + "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": "Full Name", + "length": 0, + "no_copy": 0, + "options": "", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "status", + "fieldtype": "Select", + "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": "Status", + "length": 0, + "no_copy": 0, + "options": "Active\nSuspended\nLeft", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_2", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "employee", + "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": "Employee", + "length": 0, + "no_copy": 0, + "options": "Employee", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cell_number", + "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": "Cellphone Number", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "license_details", + "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": "License Details", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "license_number", + "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": "License Number", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_8", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "issuing_date", + "fieldtype": "Date", + "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": "Issuing Date", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_10", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "expiry_date", + "fieldtype": "Date", + "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": "Expiry Date", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "driving_license_categories", + "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": "Driving License Categories", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "driving_license_category", + "fieldtype": "Table", + "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": "Driving License Category", + "length": 0, + "no_copy": 0, + "options": "Driving License Category", + "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 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "icon": "fa fa-user", + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2017-11-06 06:52:01.868222", + "modified_by": "Administrator", + "module": "HR", + "name": "Driver", + "name_case": "Title Case", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Fleet Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 0 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "search_fields": "full_name", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "full_name", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/hr/doctype/driver/driver.py b/erpnext/hr/doctype/driver/driver.py new file mode 100644 index 0000000000..2cd22cd548 --- /dev/null +++ b/erpnext/hr/doctype/driver/driver.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe.model.document import Document + +class Driver(Document): + pass diff --git a/erpnext/hr/doctype/driver/test_driver.js b/erpnext/hr/doctype/driver/test_driver.js new file mode 100644 index 0000000000..ff9f61e66a --- /dev/null +++ b/erpnext/hr/doctype/driver/test_driver.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: Driver", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Driver + () => frappe.tests.make('Driver', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/hr/doctype/driver/test_driver.py b/erpnext/hr/doctype/driver/test_driver.py new file mode 100644 index 0000000000..4bc4a8fd57 --- /dev/null +++ b/erpnext/hr/doctype/driver/test_driver.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestDriver(unittest.TestCase): + pass diff --git a/erpnext/hr/doctype/driving_license_category/__init__.py b/erpnext/hr/doctype/driving_license_category/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/hr/doctype/driving_license_category/driving_license_category.json b/erpnext/hr/doctype/driving_license_category/driving_license_category.json new file mode 100644 index 0000000000..45e38d39c9 --- /dev/null +++ b/erpnext/hr/doctype/driving_license_category/driving_license_category.json @@ -0,0 +1,161 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2017-10-17 08:19:43.142329", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "class", + "fieldtype": "Data", + "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": "Class", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "description", + "fieldtype": "Data", + "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": "Description", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "issuing_date", + "fieldtype": "Date", + "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": "Issuing Date", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "expiry_date", + "fieldtype": "Date", + "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": "Expiry Date", + "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 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2017-10-17 08:19:43.142329", + "modified_by": "Administrator", + "module": "HR", + "name": "Driving License Category", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "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 +} \ No newline at end of file diff --git a/erpnext/hr/doctype/driving_license_category/driving_license_category.py b/erpnext/hr/doctype/driving_license_category/driving_license_category.py new file mode 100644 index 0000000000..33ba138e27 --- /dev/null +++ b/erpnext/hr/doctype/driving_license_category/driving_license_category.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe.model.document import Document + +class DrivingLicenseCategory(Document): + pass diff --git a/erpnext/stock/doctype/delivery_stop/__init__.py b/erpnext/stock/doctype/delivery_stop/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.json b/erpnext/stock/doctype/delivery_stop/delivery_stop.json new file mode 100644 index 0000000000..311f70e3b7 --- /dev/null +++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.json @@ -0,0 +1,606 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2017-10-16 16:46:28.166950", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer", + "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": "Customer", + "length": 0, + "no_copy": 0, + "options": "Customer", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "address", + "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": "Address Name", + "length": 0, + "no_copy": 0, + "options": "Address", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_6", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer_address", + "fieldtype": "Small Text", + "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": "Customer Address", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "contact", + "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": "Contact Name", + "length": 0, + "no_copy": 0, + "options": "Contact", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_7", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer_contact", + "fieldtype": "Small Text", + "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": "Customer Contact", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_9", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "estimated_arrival", + "fieldtype": "Time", + "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": "Estimated Arrival", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "details", + "fieldtype": "Text Editor", + "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": "Details", + "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_bulk_edit": 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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "select_delivery_notes", + "fieldtype": "Button", + "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": "Select/Unselect Delivery Notes", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_14", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "delivery_notes", + "fieldtype": "Text", + "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 Notes", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2017-11-13 04:09:56.257540", + "modified_by": "Administrator", + "module": "Stock", + "name": "Delivery Stop", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "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 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.py b/erpnext/stock/doctype/delivery_stop/delivery_stop.py new file mode 100644 index 0000000000..768d1619f6 --- /dev/null +++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, newmatik.io / ESO Electronic Service Ottenbreit and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe.model.document import Document + +class DeliveryStop(Document): + pass diff --git a/erpnext/stock/doctype/delivery_trip/__init__.py b/erpnext/stock/doctype/delivery_trip/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.js b/erpnext/stock/doctype/delivery_trip/delivery_trip.js new file mode 100644 index 0000000000..5f855305c7 --- /dev/null +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.js @@ -0,0 +1,182 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Delivery Trip', { + refresh: function (frm) { + if (frm.doc.docstatus == 1 && frm.doc.delivery_stops.length > 0) { + frm.add_custom_button(__("Notify Customers via Email"), function () { + frm.trigger('notify_customers'); + }); + } + }, + calculate_arrival_time: function (frm) { + frappe.call({ + method: 'erpnext.stock.doctype.delivery_trip.delivery_trip.calculate_time_matrix', + freeze: true, + freeze_message: __("Updating estimated arrival times."), + args: { + name: frm.doc.name + }, + callback: function (r) { + if (r.message.error) { + frappe.throw(__("Malformatted address for " + r.message.error.destination.address + ", please fix to continue.")); + return; + } + frm.reload_doc(); + } + }); + }, + 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) { + frappe.msgprint({ + "message": __("No Delivery Note selected for Customer {}", [delivery_stop.customer]), + "title": __("Warning"), + "indicator": "orange", + "alert": 1 + }); + } + }); + 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'); + }); + } +}); + +cur_frm.fields_dict['delivery_stops'].grid.get_field("address").get_query = function (doc, cdt, cdn) { + var row = locals[cdt][cdn]; + if (row.customer) { + return { + query: 'frappe.contacts.doctype.address.address.address_query', + filters: { + link_doctype: "Customer", + link_name: row.customer + } + }; + } +}; + +cur_frm.fields_dict['delivery_stops'].grid.get_field("contact").get_query = function (doc, cdt, cdn) { + var row = locals[cdt][cdn]; + if (row.customer) { + return { + query: 'frappe.contacts.doctype.contact.contact.contact_query', + filters: { + link_doctype: "Customer", + link_name: row.customer + } + }; + } +}; + +frappe.ui.form.on('Delivery Stop', { + customer: function (frm, cdt, cdn) { + var row = locals[cdt][cdn]; + frappe.call({ + method: "erpnext.stock.doctype.delivery_trip.delivery_trip.get_contact_and_address", + args: {"name": row.customer}, + callback: function (r) { + if (r.message) { + if (r.message["shipping_address"]) { + frappe.model.set_value(cdt, cdn, "address", r.message["shipping_address"].parent); + } + if (r.message["contact_person"]) { + frappe.model.set_value(cdt, cdn, "contact", r.message["contact_person"].parent); + } + } + } + }); + }, + address: function (frm, cdt, cdn) { + var row = locals[cdt][cdn]; + frappe.call({ + method: "frappe.contacts.doctype.address.address.get_address_display", + args: {"address_dict": row.address}, + callback: function (r) { + if (r.message) { + frappe.model.set_value(cdt, cdn, "customer_address", r.message); + } + } + }); + }, + contact: function (frm, cdt, cdn) { + var row = locals[cdt][cdn]; + frappe.call({ + method: "erpnext.stock.doctype.delivery_trip.delivery_trip.get_contact_display", + args: {"contact": row.contact}, + callback: function (r) { + if (r.message) { + frappe.model.set_value(cdt, cdn, "customer_contact", r.message); + } + } + }); + }, + select_delivery_notes: function (frm, cdt, cdn) { + var row = locals[cdt][cdn]; + frappe.call({ + method: "erpnext.stock.doctype.delivery_trip.delivery_trip.get_delivery_notes", + args: {"customer": row.customer}, + callback: function (r) { + var delivery_notes = []; + $.each(r.message, function (field, value) { + delivery_notes.push(value.name); + }); + if (r.message) { + var d = new frappe.ui.Dialog({ + title: __("Select Delivery Notes"), + fields: [{fieldtype: "HTML", fieldname: "delivery_notes_html"}] + }); + var html = $(` +
+
+
+ ${__('Delivery Notes')} +
+
+ ${delivery_notes.map(delivery_note => ` +
+
+ +
+
+ `).join("")} +
+ `); + + var delivery_notes_el = d.fields_dict.delivery_notes_html.$wrapper.html(html); + + d.set_primary_action(__("Select"), function () { + var delivery_notes = delivery_notes_el.find('input[type=checkbox]:checked').map((i, el) => $(el).attr('data-delivery-note')).toArray(); + if (!delivery_notes) return; + frappe.model.set_value(cdt, cdn, "delivery_notes", delivery_notes.join(",")); + d.hide(); + }); + d.show(); + } + else { + frappe.msgprint(__("No submitted Delivery Notes found")); + } + } + }); + } +}); \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.json b/erpnext/stock/doctype/delivery_trip/delivery_trip.json new file mode 100644 index 0000000000..50e4999991 --- /dev/null +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.json @@ -0,0 +1,578 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "naming_series:", + "beta": 0, + "creation": "2017-10-16 16:45:48.293335", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "naming_series", + "fieldtype": "Select", + "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": "Series", + "length": 0, + "no_copy": 0, + "options": "TOUR-.#####", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "company", + "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": "Company", + "length": 0, + "no_copy": 0, + "options": "Company", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_2", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "email_notification_sent", + "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": "Initial Email Notification Sent", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_3", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "date", + "fieldtype": "Date", + "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": "Date", + "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": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "departure_time", + "fieldtype": "Time", + "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": "Departure Time", + "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": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_4", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "driver", + "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": "Driver", + "length": 0, + "no_copy": 0, + "options": "Driver", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "driver_name", + "fieldtype": "Data", + "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": "Driver Name", + "length": 0, + "no_copy": 0, + "options": "driver.full_name", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "vehicle", + "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": "Vehicle", + "length": 0, + "no_copy": 0, + "options": "Vehicle", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "delivery_service_stops", + "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": "Delivery Stops", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "delivery_stops", + "fieldtype": "Table", + "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 Stop", + "length": 0, + "no_copy": 0, + "options": "Delivery Stop", + "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_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!cur_frm.is_new()", + "fieldname": "calculate_arrival_time", + "fieldtype": "Button", + "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": "Calculate Estimated Arrival Times", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_13", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Delivery Notification", + "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": "Standard Reply", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "amended_from", + "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": "Amended From", + "length": 0, + "no_copy": 1, + "options": "Delivery Trip", + "permlevel": 0, + "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, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 1, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2017-11-13 03:56:09.885801", + "modified_by": "Administrator", + "module": "Stock", + "name": "Delivery Trip", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 1, + "apply_user_permissions": 0, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Fulfillment User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py new file mode 100644 index 0000000000..6923c5f033 --- /dev/null +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import datetime +import frappe +import googlemaps +from frappe import _ +from frappe.model.document import Document +from frappe.utils.user import get_user_fullname +from frappe.utils import getdate +from frappe.integrations.doctype.google_maps.google_maps import round_timedelta +from frappe.integrations.doctype.google_maps.google_maps import customer_address_format + +class DeliveryTrip(Document): + pass + +def get_default_contact(out, name): + contact_persons = frappe.db.sql( + """ + select parent, + (select is_primary_contact from tabContact c where c.name = dl.parent) + as is_primary_contact + from + `tabDynamic Link` dl + where + dl.link_doctype="Customer" and + dl.link_name=%s and + dl.parenttype = 'Contact' + """, (name), as_dict=1) + + if contact_persons: + for out.contact_person in contact_persons: + if out.contact_person.is_primary_contact: + return out.contact_person + out.contact_person = contact_persons[0] + return out.contact_person + else: + return None + +def get_default_address(out, name): + shipping_addresses = frappe.db.sql( + """ + select + parent, (select is_shipping_address from tabAddress a where a.name=dl.parent) as is_shipping_address + from `tabDynamic Link` dl + where link_doctype="Customer" and link_name=%s + and parenttype = 'Address' + """ + , (name), as_dict=1) + + if shipping_addresses: + for out.shipping_address in shipping_addresses: + if out.shipping_address.is_shipping_address: + return out.shipping_address + out.shipping_address = shipping_addresses[0] + return out.shipping_address + else: + return None + + +@frappe.whitelist() +def get_contact_and_address(name): + out = frappe._dict() + get_default_contact(out, name) + get_default_address(out, name) + return out + + +@frappe.whitelist() +def get_contact_display(contact): + contact_info = frappe.db.get_value( + "Contact", contact, + ["first_name", "last_name", "phone", "mobile_no"], + as_dict=1) + contact_info.html = """ %(first_name)s %(last_name)s
%(phone)s
%(mobile_no)s""" % { + "first_name": contact_info.first_name, + "last_name": contact_info.last_name, + "phone": contact_info.phone if contact_info.phone else "", + "mobile_no": contact_info.mobile_no if contact_info.mobile_no else "", + } + return contact_info.html + + +@frappe.whitelist() +def get_delivery_notes(customer): + return frappe.db.get_all( + "Delivery Note", + filters={'customer': customer, + 'docstatus': 1, + 'status': ('!=', 'Completed')}) + +@frappe.whitelist() +def calculate_time_matrix(name): + """Calucation and round in closest 15 minutes, delivery stops""" + + gmaps_client = frappe.db.get_single_value('Google Maps', 'client_key') + gmaps = googlemaps.Client(key=gmaps_client) + home = frappe.db.get_single_value('Google Maps', 'home_address') + + secs_15min = 900 + doc = frappe.get_doc('Delivery Trip', name) + departure_time = doc.departure_time + matrix_duration = [] + + for i, stop in enumerate(doc.delivery_stop): + + if i == 0: + # The first row is the starting pointing + origin = home + destination = customer_address_format(doc.delivery_stop[i].address) + distance_calc = gmaps.distance_matrix(origin, destination) + matrix_duration.append(distance_calc) + try: + distance_secs = distance_calc['rows'][0]['elements'][0]['duration']['value'] + except Exception as e: + frappe.throw(_("Error '{0}' occured. Arguments {1}.").format(e.message, e.args)) + stop.estimated_arrival = round_timedelta(departure_time + datetime.timedelta(0, distance_secs + secs_15min), + datetime.timedelta(minutes=15)) + stop.save() + frappe.db.commit() + else: + # Calculation based on previous + origin = customer_address_format(doc.delivery_stop[i - 1].address) + destination = customer_address_format(doc.delivery_stop[i].address) + distance_calc = gmaps.distance_matrix(origin, destination) + matrix_duration.append(distance_calc) + try: + distance_secs = distance_calc['rows'][0]['elements'][0]['duration']['value'] + except Exception as e: + frappe.throw(_("Error '{0}' occured. Arguments {1}.").format(e.message, e.args)) + stop.estimated_arrival = round_timedelta( + doc.delivery_stop[i - 1].estimated_arrival + datetime.timedelta(0, distance_secs + secs_15min), + datetime.timedelta(minutes=15)) + stop.save() + frappe.db.commit() + return matrix_duration + + +@frappe.whitelist() +def notify_customers(docname, date, driver, vehicle, sender_email, delivery_notification): + sender_name = get_user_fullname(sender_email) + delivery_stops = frappe.get_all('Delivery Stop', {"parent": docname}) + attachments = [] + + for delivery_stop in delivery_stops: + delivery_stop_info = frappe.db.get_value( + "Delivery Stop", + delivery_stop.name, + ["notified_by_email", "estimated_arrival", + "details", "contact", "delivery_notes"], + as_dict=1) + contact_info = frappe.db.get_value( + "Contact", delivery_stop_info.contact, + ["first_name", "last_name", "email_id", "gender"], + as_dict=1) + + if delivery_stop_info.delivery_notes: + delivery_notes = (delivery_stop_info.delivery_notes).split(",") + attachments = [] + for delivery_note in delivery_notes: + attachments.append( + frappe.attach_print('Delivery Note', + delivery_note, + file_name="Delivery Note", + print_format='Delivery Note')) + + if not delivery_stop_info.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 = str(delivery_stop_info.estimated_arrival)[:-3] + email_template = frappe.get_doc("Standard Reply", + delivery_notification) + message = frappe.render_template( + email_template.response, + dict(contact_info=contact_info, sender_name=sender_name, + details=delivery_stop_info.details, + estimated_arrival=estimated_arrival, + date=getdate(date).strftime('%d.%m.%y'), vehicle=vehicle, + driver_info=driver_info, + sender_designation=sender_designation) + ) + 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)) \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.js b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.js new file mode 100644 index 0000000000..b6d6d1af64 --- /dev/null +++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.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 Trip", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Delivery Trip + () => frappe.tests.make('Delivery Trip', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py new file mode 100644 index 0000000000..6ac86960d4 --- /dev/null +++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import erpnext +import unittest +from frappe.utils import nowdate, add_days +from erpnext.tests.utils import create_test_contact_and_address +from erpnext.stock.doctype.delivery_trip.delivery_trip import notify_customers + +class TestDeliveryTrip(unittest.TestCase): + def setUp(self): + create_driver() + create_vehicle() + create_test_contact_and_address() + + def test_delivery_trip(self): + 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 = "Newton Scmander" + delivery_trip.vehicle = "JB 007" + delivery_trip.append("delivery_stops", { + "customer": "_Test Customer", + "address": "_Test Address for Customer", + "contact": '_Test Contact for _Test Customer - _Test Customer' + }) + 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.assertEquals(delivery_trip.get("delivery_stops")[0].notified_by_email, 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.insert() + + +def create_vehicle(): + if not frappe.db.exists("Vehicle", "JB 007"): + vehicle = frappe.get_doc({ + "doctype": "Vehicle", + "license_plate": "JB 007", + "make": "Maruti", + "model": "PCM", + "last_odometer": 5000, + "acquisition_date": frappe.utils.nowdate(), + "location": "Mumbai", + "chassis_no": "1234ABCD", + "vehicle_value": frappe.utils.flt(500000) + }) + vehicle.insert() diff --git a/requirements.txt b/requirements.txt index 0bfd3df0ac..a6cfaf2ce4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ frappe unidecode pygithub +googlemaps