From 2678ed181a04a76934e075fe3d1e5f6734e172fc Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 18 Dec 2013 13:28:40 +0530 Subject: [PATCH 1/6] [fix] [issue] webnotes/erpnext#1191 - set expected delivery date in production order --- .../production_order/production_order.js | 86 ++++++++++--------- .../production_order/production_order.py | 24 +++--- .../production_order/production_order.txt | 10 ++- .../production_planning_tool.py | 1 - patches/patch_list.py | 1 + setup/page/setup_wizard/setup_wizard.py | 4 + 6 files changed, 74 insertions(+), 52 deletions(-) diff --git a/manufacturing/doctype/production_order/production_order.js b/manufacturing/doctype/production_order/production_order.js index 2277262fd28..31900ea57af 100644 --- a/manufacturing/doctype/production_order/production_order.js +++ b/manufacturing/doctype/production_order/production_order.js @@ -1,28 +1,56 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt -cur_frm.cscript.onload = function(doc, dt, dn) { - if (!doc.status) doc.status = 'Draft'; - cfn_set_fields(doc, dt, dn); -} +$.extend(cur_frm.cscript, { + onload: function (doc, dt, dn) { -cur_frm.cscript.refresh = function(doc, dt, dn) { - cur_frm.dashboard.reset(); - erpnext.hide_naming_series(); - cur_frm.set_intro(""); - cfn_set_fields(doc, dt, dn); + if (!doc.status) doc.status = 'Draft'; + cfn_set_fields(doc, dt, dn); - if(doc.docstatus===0 && !doc.__islocal) { - cur_frm.set_intro(wn._("Submit this Production Order for further processing.")); - } else if(doc.docstatus===1) { - var percent = flt(doc.produced_qty) / flt(doc.qty) * 100; - cur_frm.dashboard.add_progress(cint(percent) + "% " + wn._("Complete"), percent); + this.frm.add_fetch("sales_order", "delivery_date", "expected_delivery_date"); + }, - if(doc.status === "Stopped") { - cur_frm.dashboard.set_headline_alert(wn._("Stopped"), "alert-danger", "icon-stop"); + refresh: function(doc, dt, dn) { + this.frm.dashboard.reset(); + erpnext.hide_naming_series(); + this.frm.set_intro(""); + cfn_set_fields(doc, dt, dn); + + if (doc.docstatus === 0 && !doc.__islocal) { + this.frm.set_intro(wn._("Submit this Production Order for further processing.")); + } else if (doc.docstatus === 1) { + var percent = flt(doc.produced_qty) / flt(doc.qty) * 100; + this.frm.dashboard.add_progress(cint(percent) + "% " + wn._("Complete"), percent); + + if(doc.status === "Stopped") { + this.frm.dashboard.set_headline_alert(wn._("Stopped"), "alert-danger", "icon-stop"); + } } + }, + + production_item: function(doc) { + return this.frm.call({ + method: "get_item_details", + args: { item: doc.production_item } + }); + }, + + make_se: function(purpose) { + var me = this; + + wn.call({ + method:"manufacturing.doctype.production_order.production_order.make_stock_entry", + args: { + "production_order_id": me.frm.doc.name, + "purpose": purpose + }, + callback: function(r) { + var doclist = wn.model.sync(r.message); + wn.set_route("Form", doclist[0].doctype, doclist[0].name); + } + }); } -} +}); var cfn_set_fields = function(doc, dt, dn) { if (doc.docstatus == 1) { @@ -38,13 +66,6 @@ var cfn_set_fields = function(doc, dt, dn) { } } -cur_frm.cscript.production_item = function(doc) { - return cur_frm.call({ - method: "get_item_details", - args: { item: doc.production_item } - }); -} - cur_frm.cscript['Stop Production Order'] = function() { var doc = cur_frm.doc; var check = confirm(wn._("Do you really want to stop production order: " + doc.name)); @@ -57,7 +78,7 @@ cur_frm.cscript['Unstop Production Order'] = function() { var doc = cur_frm.doc; var check = confirm(wn._("Do really want to unstop production order: " + doc.name)); if (check) - return $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();}); + return $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();}); } cur_frm.cscript['Transfer Raw Materials'] = function() { @@ -68,20 +89,6 @@ cur_frm.cscript['Update Finished Goods'] = function() { cur_frm.cscript.make_se('Manufacture/Repack'); } -cur_frm.cscript.make_se = function(purpose) { - wn.call({ - method:"manufacturing.doctype.production_order.production_order.make_stock_entry", - args: { - "production_order_id": cur_frm.doc.name, - "purpose": purpose - }, - callback: function(r) { - var doclist = wn.model.sync(r.message); - wn.set_route("Form", doclist[0].doctype, doclist[0].name); - } - }) -} - cur_frm.fields_dict['production_item'].get_query = function(doc) { return { filters:[ @@ -98,7 +105,6 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) { } } - cur_frm.set_query("bom_no", function(doc) { if (doc.production_item) { return{ diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py index c5b2b04791e..bcb13f8a226 100644 --- a/manufacturing/doctype/production_order/production_order.py +++ b/manufacturing/doctype/production_order/production_order.py @@ -8,7 +8,6 @@ from webnotes.utils import cstr, flt, nowdate from webnotes.model.code import get_obj from webnotes import msgprint, _ - class OverProductionError(webnotes.ValidationError): pass class DocType: @@ -37,15 +36,20 @@ class DocType: and is_active=1 and item=%s""" , (self.doc.bom_no, self.doc.production_item), as_dict =1) if not bom: - msgprint("""Incorrect BOM: %s entered. + webnotes.throw("""Incorrect BOM: %s entered. May be BOM not exists or inactive or not submitted - or for some other item.""" % cstr(self.doc.bom_no), raise_exception=1) + or for some other item.""" % cstr(self.doc.bom_no)) def validate_sales_order(self): if self.doc.sales_order: - if not webnotes.conn.sql("""select name from `tabSales Order` - where name=%s and docstatus = 1""", self.doc.sales_order): - msgprint("Sales Order: %s is not valid" % self.doc.sales_order, raise_exception=1) + so = webnotes.conn.sql("""select name, delivery_date from `tabSales Order` + where name=%s and docstatus = 1""", self.doc.sales_order, as_dict=1)[0] + + if not so.name: + webnotes.throw("Sales Order: %s is not valid" % self.doc.sales_order) + + if not self.doc.expected_delivery_date: + self.doc.expected_delivery_date = so.delivery_date self.validate_production_order_against_so() @@ -76,11 +80,11 @@ class DocType: so_qty = flt(so_item_qty) + flt(dnpi_qty) if total_qty > so_qty: - webnotes.msgprint(_("Total production order qty for item") + ": " + + webnotes.throw(_("Total production order qty for item") + ": " + cstr(self.doc.production_item) + _(" against sales order") + ": " + cstr(self.doc.sales_order) + _(" will be ") + cstr(total_qty) + ", " + _("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" + - _("Please reduce qty."), raise_exception=OverProductionError) + _("Please reduce qty."), exc=OverProductionError) def stop_unstop(self, status): """ Called from client side on Stop/Unstop event""" @@ -114,8 +118,8 @@ class DocType: stock_entry = webnotes.conn.sql("""select name from `tabStock Entry` where production_order = %s and docstatus = 1""", self.doc.name) if stock_entry: - msgprint("""Submitted Stock Entry %s exists against this production order. - Hence can not be cancelled.""" % stock_entry[0][0], raise_exception=1) + webnotes.throw("""Submitted Stock Entry %s exists against this production order. + Hence can not be cancelled.""" % stock_entry[0][0]) webnotes.conn.set(self.doc,'status', 'Cancelled') self.update_planned_qty(-self.doc.qty) diff --git a/manufacturing/doctype/production_order/production_order.txt b/manufacturing/doctype/production_order/production_order.txt index 85c7c838818..5e76c0e18f3 100644 --- a/manufacturing/doctype/production_order/production_order.txt +++ b/manufacturing/doctype/production_order/production_order.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-10 16:34:16", "docstatus": 0, - "modified": "2013-11-02 14:05:44", + "modified": "2013-12-18 13:22:14", "modified_by": "Administrator", "owner": "Administrator" }, @@ -136,6 +136,14 @@ "oldfieldtype": "Currency", "read_only": 1 }, + { + "depends_on": "sales_order", + "doctype": "DocField", + "fieldname": "expected_delivery_date", + "fieldtype": "Date", + "label": "Expected Delivery Date", + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "warehouses", diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index c1185a1b128..29232f5f519 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -186,7 +186,6 @@ class DocType: else : msgprint(_("No Production Order created.")) - def get_distinct_items_and_boms(self): """ Club similar BOM and item for processing bom_dict { diff --git a/patches/patch_list.py b/patches/patch_list.py index 9400e08872e..1e5f1dee0f0 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -258,4 +258,5 @@ patch_list = [ "execute:webnotes.delete_doc('Report', 'Stock Ledger') #2013-11-29", "execute:webnotes.delete_doc('Report', 'Payment Collection With Ageing')", "execute:webnotes.delete_doc('Report', 'Payment Made With Ageing')", + "execute:webnotes.delete_doc('DocType', 'Warehouse Type')", ] \ No newline at end of file diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index bf149059a1a..e431b2ad5e2 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -158,6 +158,10 @@ def set_defaults(args): hr_settings.doc.emp_created_by = "Naming Series" hr_settings.save() + email_settings = webnotes.bean("Email Settings") + email_settings.doc.send_print_in_body_and_attachment = 1 + email_settings.save() + # control panel cp = webnotes.doc("Control Panel", "Control Panel") cp.company_name = args["company_name"] From fcbd4d7638169eba6bc940d96d15d33b16a8a52f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 18 Dec 2013 14:53:36 +0530 Subject: [PATCH 2/6] Removed sales_order_no from no_copy in material request item --- stock/doctype/material_request_item/material_request_item.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/doctype/material_request_item/material_request_item.txt b/stock/doctype/material_request_item/material_request_item.txt index 15884a3b5ec..e0b9330baa7 100644 --- a/stock/doctype/material_request_item/material_request_item.txt +++ b/stock/doctype/material_request_item/material_request_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-22 01:28:02", "docstatus": 0, - "modified": "2013-11-03 20:36:45", + "modified": "2013-12-18 14:52:02", "modified_by": "Administrator", "owner": "Administrator" }, @@ -219,7 +219,7 @@ "fieldname": "sales_order_no", "fieldtype": "Link", "label": "Sales Order No", - "no_copy": 1, + "no_copy": 0, "options": "Sales Order", "print_hide": 1, "read_only": 1 From 48156e3d8b89f0bc9baf94f098208bcb48469bde Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 18 Dec 2013 18:51:20 +0530 Subject: [PATCH 3/6] fixes in stock projected qty report --- stock/report/stock_projected_qty/stock_projected_qty.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stock/report/stock_projected_qty/stock_projected_qty.py b/stock/report/stock_projected_qty/stock_projected_qty.py index 11d519558de..d116d03b59c 100644 --- a/stock/report/stock_projected_qty/stock_projected_qty.py +++ b/stock/report/stock_projected_qty/stock_projected_qty.py @@ -26,10 +26,10 @@ def execute(filters=None): def get_columns(): return ["Item Code:Link/Item:140", "Item Name::100", "Description::200", - "Brand:Link/Brand:100", "Warehouse:Link/Warehouse:120", "UOM:Link/UOM:100", - "Actual Qty:Float:100", "Planned Qty:Float:100", "Requested Qty:Float:110", - "Ordered Qty:Float:100", "Reserved Qty:Float:100", "Projected Qty:Float:100", - "Reorder Level:Float:100", "Reorder Qty:Float:100"] + "Item Group:Link/Item Group:100", "Brand:Link/Brand:100", "Warehouse:Link/Warehouse:120", + "UOM:Link/UOM:100", "Actual Qty:Float:100", "Planned Qty:Float:100", + "Requested Qty:Float:110", "Ordered Qty:Float:100", "Reserved Qty:Float:100", + "Projected Qty:Float:100", "Reorder Level:Float:100", "Reorder Qty:Float:100"] def get_item_conditions(filters): conditions = [] From 85800fa92944c10a561732b2f9db86b05e26097f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 19 Dec 2013 10:57:43 +0530 Subject: [PATCH 4/6] fixes in item validation --- stock/doctype/item/item.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index b5884b41116..01f1d9f38f8 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -123,14 +123,14 @@ class DocType(DocListController, WebsiteGenerator): msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1) def check_for_active_boms(self): - if self.doc.is_active != "Yes" or self.doc.is_purchase_item != "Yes": + if self.doc.is_purchase_item != "Yes": bom_mat = webnotes.conn.sql("""select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2 where t2.name = t1.parent and t1.item_code =%s and ifnull(t1.bom_no, '') = '' and t2.is_active = 1 and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name) if bom_mat and bom_mat[0][0]: - webnotes.throw(_("Item must be active and purchase item, \ + webnotes.throw(_("Item must be a purchase item, \ as it is present in one or many Active BOMs")) if self.doc.is_manufactured_item != "Yes": From fe6409debfda613528059377dc46ea9e929caf43 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 19 Dec 2013 11:41:10 +0530 Subject: [PATCH 5/6] fix company email digest patch --- patches/1311/p07_scheduler_errors_digest.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/patches/1311/p07_scheduler_errors_digest.py b/patches/1311/p07_scheduler_errors_digest.py index 6811571ab91..4527f187259 100644 --- a/patches/1311/p07_scheduler_errors_digest.py +++ b/patches/1311/p07_scheduler_errors_digest.py @@ -13,11 +13,9 @@ def execute(): return # no default company - company = webnotes.conn.get_default("company") - if not company: - company = webnotes.conn.sql_list("select name from `tabCompany`") - if company: - company = company[0] + company = webnotes.conn.sql_list("select name from `tabCompany`") + if company: + company = company[0] if not company: return @@ -31,4 +29,4 @@ def execute(): "recipient_list": "\n".join(system_managers), "scheduler_errors": 1 }) - edigest.insert() \ No newline at end of file + edigest.insert() From 1644fce273b7baa78d74ed4a74416035783df29d Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 19 Dec 2013 12:12:38 +0600 Subject: [PATCH 6/6] bumped to version 3.3.3 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 68782da730e..07b0a13c902 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.3.2", + "app_version": "3.3.3", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": {