diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 07a80b87bd..af3f9a6c11 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -291,9 +291,9 @@ "search_index": 1, "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 1ddce628a2..d56c3bd5c3 100755 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -148,7 +148,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 0, "in_standard_filter": 0, "label": "Reqd By Date", "length": 0, diff --git a/erpnext/demo/user/purchase.py b/erpnext/demo/user/purchase.py index 960a3169cf..82983f0a71 100644 --- a/erpnext/demo/user/purchase.py +++ b/erpnext/demo/user/purchase.py @@ -103,6 +103,7 @@ def make_material_request(item_code, qty): mr.material_request_type = "Purchase" mr.transaction_date = frappe.flags.current_date + mr.schedule_date = frappe.utils.add_days(mr.transaction_date, 7) mr.append("items", { "doctype": "Material Request Item", diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 1d57a2faa0..3ef7be1494 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -515,7 +515,8 @@ class ProductionPlanningTool(Document): "transaction_date": nowdate(), "status": "Draft", "company": self.company, - "requested_by": frappe.session.user + "requested_by": frappe.session.user, + "schedule_date": add_days(nowdate(), cint(item_wrapper.lead_time_days)), }) material_request.update({"material_request_type": item_wrapper.default_material_request_type}) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 113c40212f..70122ba220 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -449,3 +449,4 @@ erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts erpnext.patches.v8_9.set_default_fields_in_variant_settings erpnext.patches.v8_9.update_billing_gstin_for_indian_account erpnext.patches.v9_0.fix_subscription_next_date +erpnext.patches.v9_0.set_schedule_date_for_material_request diff --git a/erpnext/patches/v9_0/set_schedule_date_for_material_request.py b/erpnext/patches/v9_0/set_schedule_date_for_material_request.py new file mode 100644 index 0000000000..39d4d413a1 --- /dev/null +++ b/erpnext/patches/v9_0/set_schedule_date_for_material_request.py @@ -0,0 +1,21 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doctype("Material Request") + frappe.reload_doctype("Material Request Item") + + if not frappe.db.has_column("Material Request", "schedule_date"): + return + + #Update only submitted MR + for mr in frappe.get_all("Material Request", filters= [["docstatus", "=", 1]], fields=["name"]): + material_request = frappe.get_doc("Material Request", mr) + if material_request.items: + if not material_request.schedule_date: + max_schedule_date = max([d.schedule_date for d in material_request.items]) + frappe.db.set_value("Material Request", mr, + "schedule_date", max_schedule_date, update_modified=False) \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 00d2121897..6f70ebe07e 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -92,7 +92,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( // delivery note if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) { this.frm.add_custom_button(__('Delivery'), - function() { me.make_delivery_note_based_on_delivery_note(); }, __("Make")); + function() { me.make_delivery_note_based_on_delivery_date(); }, __("Make")); this.frm.add_custom_button(__('Production Order'), function() { me.make_production_order() }, __("Make")); @@ -270,7 +270,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( }) }, - make_delivery_note_based_on_delivery_note: function() { + make_delivery_note_based_on_delivery_date: function() { var me = this; var delivery_dates = []; diff --git a/erpnext/setup/setup_wizard/sample_data.py b/erpnext/setup/setup_wizard/sample_data.py index bc26e09677..43911f06c1 100644 --- a/erpnext/setup/setup_wizard/sample_data.py +++ b/erpnext/setup/setup_wizard/sample_data.py @@ -73,6 +73,7 @@ def make_material_request(items): mr = frappe.get_doc({ "doctype": "Material Request", "material_request_type": "Purchase", + "schedule_date": frappe.utils.add_days(frappe.utils.nowdate(), 7), "items": [{ "schedule_date": frappe.utils.add_days(frappe.utils.nowdate(), 7), "item_code": i.name, diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 7043fb7ba8..4e4b0f7303 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -17,6 +17,9 @@ frappe.ui.form.on('Material Request', { // add item, if previous view was item erpnext.utils.add_item(frm); + //set schedule_date + set_schedule_date(frm); + // formatter for material request item frm.set_indicator_formatter('item_code', function(doc) { return (doc.qty<=doc.ordered_qty) ? "green" : "orange" }), @@ -38,13 +41,19 @@ frappe.ui.form.on("Material Request Item", { }, item_code: function(frm, doctype, name) { - frm.script_manager.copy_from_first_row('items', frm.selected_doc, - 'schedule_date'); + set_schedule_date(frm); }, schedule_date: function(frm, cdt, cdn) { - erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "schedule_date"); - } + var row = locals[cdt][cdn]; + if (row.schedule_date) { + if(!frm.doc.schedule_date) { + erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "schedule_date"); + } else { + set_schedule_date(frm); + } + } + } }); erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.extend({ @@ -227,6 +236,28 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten } } }); + }, + + validate: function() { + set_schedule_date(this.frm); + }, + + items_add: function(doc, cdt, cdn) { + var row = frappe.get_doc(cdt, cdn); + if(doc.schedule_date) { + row.schedule_date = doc.schedule_date; + refresh_field("schedule_date", cdn, "items"); + } else { + this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]); + } + }, + + items_on_form_rendered: function() { + set_schedule_date(this.frm); + }, + + schedule_date: function() { + set_schedule_date(this.frm); } }); @@ -246,3 +277,9 @@ cur_frm.cscript['Unstop Material Request'] = function(){ cur_frm.refresh(); }); }; + +function set_schedule_date(frm) { + if(frm.doc.schedule_date){ + erpnext.utils.copy_value_in_all_row(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date"); + } +} \ No newline at end of file diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json index 87cde0d3e2..ba373453be 100644 --- a/erpnext/stock/doctype/material_request/material_request.json +++ b/erpnext/stock/doctype/material_request/material_request.json @@ -42,6 +42,38 @@ "set_only_once": 0, "unique": 0 }, + { + "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": 1, + "in_standard_filter": 0, + "label": "Series", + "length": 0, + "no_copy": 1, + "oldfieldname": "naming_series", + "oldfieldtype": "Select", + "options": "MREQ-", + "permlevel": 0, + "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": 1, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 1, @@ -133,69 +165,33 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "naming_series", - "fieldtype": "Select", + "fieldname": "schedule_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": "Series", - "length": 0, - "no_copy": 1, - "oldfieldname": "naming_series", - "oldfieldtype": "Select", - "options": "MREQ-", - "permlevel": 0, - "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": 1, - "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": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Amended From", + "label": "Required Date", "length": 0, - "no_copy": 1, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Material Request", + "no_copy": 0, "permlevel": 0, - "print_hide": 1, + "precision": "", + "print_hide": 0, "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 1, + "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, - "unique": 0, - "width": "150px" + "unique": 0 }, { "allow_bulk_edit": 0, @@ -232,6 +228,40 @@ "unique": 0, "width": "150px" }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "amended_from", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "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, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Material Request", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "150px" + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -686,7 +716,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-26 19:43:31.823549", + "modified": "2017-10-05 18:24:17.148782", "modified_by": "Administrator", "module": "Stock", "name": "Material Request", diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 65263a0694..4e9d290e80 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -54,9 +54,18 @@ class MaterialRequest(BuyingController): frappe.throw(_("Material Request of maximum {0} can be made for Item {1} against Sales Order {2}").format(actual_so_qty - already_indented, item, so_no)) def validate_schedule_date(self): - for d in self.get('items'): - if d.schedule_date and getdate(d.schedule_date) < getdate(self.transaction_date): - frappe.throw(_("Expected Date cannot be before Material Request Date")) + if not self.schedule_date: + self.schedule_date = max([d.schedule_date for d in self.get("items")]) + + if self.schedule_date: + for d in self.get('items'): + if not d.schedule_date: + d.schedule_date = self.schedule_date + + if d.schedule_date and getdate(d.schedule_date) < getdate(self.transaction_date): + frappe.throw(_("Expected Date cannot be before Material Request Date")) + else: + frappe.throw(_("Please enter Schedule Date")) # Validate # --------------------- @@ -70,9 +79,9 @@ class MaterialRequest(BuyingController): self.status = "Draft" from erpnext.controllers.status_updater import validate_status - validate_status(self.status, ["Draft", "Submitted", "Stopped", "Cancelled", "Pending", - "Partially Ordered", "Ordered", "Issued", "Transferred"] - ) + validate_status(self.status, + ["Draft", "Submitted", "Stopped", "Cancelled", "Pending", + "Partially Ordered", "Ordered", "Issued", "Transferred"]) validate_for_items(self) diff --git a/erpnext/stock/doctype/material_request/test_records.json b/erpnext/stock/doctype/material_request/test_records.json index 09d1912ed7..1c714969eb 100644 --- a/erpnext/stock/doctype/material_request/test_records.json +++ b/erpnext/stock/doctype/material_request/test_records.json @@ -29,7 +29,8 @@ ], "material_request_type": "Purchase", "naming_series": "_T-Material Request-", - "transaction_date": "2013-02-18" + "transaction_date": "2013-02-18", + "schedule_date": "2013-02-19" }, { "company": "_Test Company", @@ -43,13 +44,14 @@ "item_name": "_Test FG Item", "parentfield": "items", "qty": 5, - "schedule_date": "2013-02-18", + "schedule_date": "2013-02-19", "uom": "_Test UOM 1", "warehouse": "_Test Warehouse - _TC" } ], "material_request_type": "Manufacture", "naming_series": "_T-Material Request-", - "transaction_date": "2013-02-18" + "transaction_date": "2013-02-18", + "schedule_date": "2013-02-19" } ] \ No newline at end of file diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request.js b/erpnext/stock/doctype/material_request/tests/test_material_request.js index 22d1088cfe..1ae41f5898 100644 --- a/erpnext/stock/doctype/material_request/tests/test_material_request.js +++ b/erpnext/stock/doctype/material_request/tests/test_material_request.js @@ -11,14 +11,25 @@ QUnit.test("test material request", function(assert) { {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 5)}, {'qty': 5}, {'item_code': 'Test Product 1'}, + ], + [ + {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 6)}, + {'qty': 2}, + {'item_code': 'Test Product 2'}, ] ]}, ]); }, () => cur_frm.save(), () => { + assert.ok(cur_frm.doc.schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 5), "Schedule Date correct"); + // get_item_details assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + assert.ok(cur_frm.doc.items[0].schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 5), "Schedule Date correct"); + + assert.ok(cur_frm.doc.items[1].item_name=='Test Product 2', "Item name correct"); + assert.ok(cur_frm.doc.items[1].schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 6), "Schedule Date correct"); }, () => frappe.tests.click_button('Submit'), () => frappe.tests.click_button('Yes'), diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index 01a6a6d547..8da9f110f0 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -121,7 +121,8 @@ def create_material_request(material_requests): mr.update({ "company": company, "transaction_date": nowdate(), - "material_request_type": "Material Transfer" if request_type=="Transfer" else request_type + "material_request_type": "Material Transfer" if request_type=="Transfer" else request_type, + "schedule_date": add_days(nowdate(), cint(items[0].lead_time_days)) }) for d in items: