diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a2dc172767..c66621856f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.14' +__version__ = '10.1.15' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index b7f96c6a3d..68625db65f 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -61,7 +61,10 @@ frappe.query_reports["General Ledger"] = { "label": __("Party Type"), "fieldtype": "Link", "options": "Party Type", - "default": "" + "default": "", + on_change: function() { + frappe.query_report_filters_by_name.party.set_value(""); + } }, { "fieldname":"party", @@ -82,8 +85,7 @@ frappe.query_reports["General Ledger"] = { frappe.query_report_filters_by_name.party_name.set_value(""); return; } - - var fieldname = frappe.scrub(party_type) + "_name"; + var fieldname = erpnext.utils.get_party_name(party_type) || "name"; frappe.db.get_value(party_type, party, fieldname, function(value) { frappe.query_report_filters_by_name.party_name.set_value(value[fieldname]); }); diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 70ab67f7d0..4789f9f978 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -81,7 +81,7 @@ def set_account_currency(filters): if gle_currency: account_currency = gle_currency else: - account_currency = None if filters.party_type == "Employee" else \ + account_currency = None if filters.party_type in ["Employee", "Student", "Shareholder"] else \ frappe.db.get_value(filters.party_type, filters.party, "default_currency") filters["account_currency"] = account_currency or filters.company_currency diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index fdf74ccbfb..c97db6db10 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -226,7 +226,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( me.frm.doc['supplied_items'].forEach((item, index) => { if (item.rm_item_code && item.main_item_code) { me.raw_material_data.push ({ - 'name':index, + 'name':item.name, 'item_code': item.main_item_code, 'rm_item_code': item.rm_item_code, 'item_name': item.rm_item_code, diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index e8e851d513..830e5a4610 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -285,7 +285,7 @@ class StatusUpdater(Document): ifnull((select ifnull(sum(if(%(target_ref_field)s > %(target_field)s, abs(%(target_field)s), abs(%(target_ref_field)s))), 0) / sum(abs(%(target_ref_field)s)) * 100 - from `tab%(target_dt)s` where parent="%(name)s" having sum(abs(%(target_ref_field)s)) > 0), 0), 2) + from `tab%(target_dt)s` where parent="%(name)s" having sum(abs(%(target_ref_field)s)) > 0), 0), 6) %(update_modified)s where name='%(name)s'""" % args) @@ -293,7 +293,7 @@ class StatusUpdater(Document): if args.get('status_field'): frappe.db.sql("""update `tab%(target_parent_dt)s` set %(status_field)s = if(%(target_parent_field)s<0.001, - 'Not %(keyword)s', if(%(target_parent_field)s>=99.99, + 'Not %(keyword)s', if(%(target_parent_field)s>=99.999999, 'Fully %(keyword)s', 'Partly %(keyword)s')) where name='%(name)s'""" % args) diff --git a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.js b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.js index 4f8ce6d19c..2e54a2febf 100644 --- a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.js +++ b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.js @@ -16,6 +16,12 @@ frappe.ui.form.on("Program Enrollment Tool", { }); }, + get_students_from: function(frm) { + if (frm.doc.get_students_from == "Student Applicant") { + frm.dashboard.add_comment(__('Only the Student Applicant with the status "Approved" will be selected in the table below.')); + } + }, + "get_students": function(frm) { frm.set_value("students",[]); frappe.call({ diff --git a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json index b846bc6d5b..08c4f4fce6 100644 --- a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json +++ b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -12,6 +13,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -21,6 +23,8 @@ "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": "Operation", @@ -38,9 +42,11 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -50,6 +56,8 @@ "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": "Workstation", @@ -67,9 +75,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,6 +89,8 @@ "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", @@ -95,9 +107,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -107,6 +121,8 @@ "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, @@ -120,9 +136,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -132,6 +150,8 @@ "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": "Hour Rate", @@ -149,9 +169,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -162,7 +184,9 @@ "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, - "in_list_view": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Operation Time ", "length": 0, @@ -179,9 +203,11 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -191,6 +217,8 @@ "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": "Operating Cost", @@ -208,9 +236,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -220,6 +250,8 @@ "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": "Base Hour Rate(Company Currency)", @@ -236,9 +268,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -249,6 +283,8 @@ "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": "Operating Cost(Company Currency)", @@ -265,9 +301,11 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -277,6 +315,8 @@ "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": "Image", @@ -292,20 +332,21 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-02-10 07:12:41.255544", + "modified": "2018-03-26 09:55:28.107451", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Operation", @@ -314,6 +355,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index fca413482b..92b33385ec 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -514,3 +514,4 @@ erpnext.patches.v10_0.update_reserved_qty_for_purchase_order erpnext.patches.v10_0.update_hub_connector_domain erpnext.patches.v10_0.set_student_party_type erpnext.patches.v10_0.update_project_in_sle +erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract diff --git a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py b/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py new file mode 100644 index 0000000000..8a456382ab --- /dev/null +++ b/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py @@ -0,0 +1,29 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe +from erpnext.stock.utils import get_bin + +def execute(): + for d in frappe.db.sql(""" + select distinct rm_item_code, reserve_warehouse + from `tabPurchase Order Item Supplied` + where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""): + + try: + bin_doc = get_bin(d[0], d[1]) + bin_doc.update_reserved_qty_for_sub_contracting() + except: + pass + + for d in frappe.db.sql("""select distinct item_code, source_warehouse + from `tabProduction Order Item` + where docstatus=1 and transferred_qty > required_qty + and source_warehouse is not null and source_warehouse != ''""", as_list=1): + + try: + bin_doc = get_bin(d[0], d[1]) + bin_doc.update_reserved_qty_for_production() + except: + pass \ No newline at end of file diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index d50fa195db..37291d7500 100644 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -111,6 +111,12 @@ $.extend(erpnext.utils, { } }, + get_party_name: function(party_type) { + var dict = {'Customer': 'customer_name', 'Supplier': 'supplier_name', 'Employee': 'employee_name', + 'Member': 'member_name'}; + return dict[party_type]; + }, + copy_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname) { var d = locals[dt][dn]; if(d[fieldname]){ diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index e66f142395..90aecde4a5 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -109,8 +109,8 @@ class Gstr1Report(object): customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type}) if self.filters.get("type_of_business") == "B2B": - conditions += " and invoice_type != 'Export' and is_return != 1 and customer in ('{0}')".\ - format("', '".join([frappe.db.escape(c.name) for c in customers])) + conditions += """ and ifnull(invoice_type, '') != 'Export' and is_return != 1 + and customer in ('{0}')""".format("', '".join([frappe.db.escape(c.name) for c in customers])) if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): b2c_limit = frappe.db.get_single_value('GSt Settings', 'b2c_limit') diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py index 679e567d42..0a2e96878f 100644 --- a/erpnext/regional/report/gstr_2/gstr_2.py +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -84,7 +84,7 @@ class Gstr2Report(Gstr1Report): conditions += opts[1] if self.filters.get("type_of_business") == "B2B": - conditions += "and invoice_type != 'Export' and is_return != 1 " + conditions += "and ifnull(invoice_type, '') != 'Export' and is_return != 1 " elif self.filters.get("type_of_business") == "CDNR": conditions += """ and is_return = 1 """ diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 0aa4cf444b..fc9254b2a3 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -96,14 +96,14 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( if (this.frm.has_perm("submit")) { // close - if(flt(doc.per_delivered, 2) < 100 || flt(doc.per_billed) < 100) { + if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) { this.frm.add_custom_button(__('Close'), function() { me.close_sales_order() }, __("Status")) } } // delivery note - if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) { + if(flt(doc.per_delivered, 6) < 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_date(); }, __("Make")); this.frm.add_custom_button(__('Work Order'), @@ -113,20 +113,20 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( } // sales invoice - if(flt(doc.per_billed, 2) < 100) { + if(flt(doc.per_billed, 6) < 100) { this.frm.add_custom_button(__('Invoice'), function() { me.make_sales_invoice() }, __("Make")); } // material request if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 - && flt(doc.per_delivered, 2) < 100) { + && flt(doc.per_delivered, 6) < 100) { this.frm.add_custom_button(__('Material Request'), function() { me.make_material_request() }, __("Make")); } // make purchase order - if(flt(doc.per_delivered, 2) < 100 && allow_purchase) { + if(flt(doc.per_delivered, 6) < 100 && allow_purchase) { this.frm.add_custom_button(__('Purchase Order'), function() { me.make_purchase_order() }, __("Make")); } @@ -229,6 +229,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( {fieldtype:'Data', fieldname:'sales_order_item', reqd: 1, label: __('Sales Order Item'), hidden:1} ], + data: r.message, get_data: function() { return r.message } diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 34272b211a..8c27a9747c 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -360,6 +360,7 @@ class SalesOrder(SellingController): where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0]) if pending_qty: items.append(dict( + name= i.name, item_code= i.item_code, bom = bom, warehouse = i.warehouse, diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js index 9751935183..43c91b9568 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_list.js +++ b/erpnext/selling/doctype/sales_order/sales_order_list.js @@ -6,15 +6,15 @@ frappe.listview_settings['Sales Order'] = { return [__("Closed"), "green", "status,=,Closed"]; } else if (doc.order_type !== "Maintenance" - && flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) { + && flt(doc.per_delivered, 6) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) { // to bill & overdue return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"]; } else if (doc.order_type !== "Maintenance" - && flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") { + && flt(doc.per_delivered, 6) < 100 && doc.status!=="Closed") { // not delivered - if(flt(doc.per_billed, 2) < 100) { + if(flt(doc.per_billed, 6) < 100) { // not delivered & not billed return [__("To Deliver and Bill"), "orange", @@ -26,14 +26,14 @@ frappe.listview_settings['Sales Order'] = { "per_delivered,<,100|per_billed,=,100|status,!=,Closed"]; } - } else if ((doc.order_type === "Maintenance" || flt(doc.per_delivered, 2) == 100) - && flt(doc.per_billed, 2) < 100 && doc.status!=="Closed") { + } else if ((doc.order_type === "Maintenance" || flt(doc.per_delivered, 6) == 100) + && flt(doc.per_billed, 6) < 100 && doc.status!=="Closed") { // to bill return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"]; - } else if((doc.order_type === "Maintenance" || flt(doc.per_delivered, 2) == 100) - && flt(doc.per_billed, 2) == 100 && doc.status!=="Closed") { + } else if((doc.order_type === "Maintenance" || flt(doc.per_delivered, 6) == 100) + && flt(doc.per_billed, 6) == 100 && doc.status!=="Closed") { return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Closed"]; } diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index d8ed37ea50..acff76dc95 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -76,14 +76,16 @@ class Bin(Document): def update_reserved_qty_for_production(self): '''Update qty reserved for production from Production Item tables in open work orders''' - self.reserved_qty_for_production = frappe.db.sql('''select sum(required_qty - transferred_qty) + self.reserved_qty_for_production = frappe.db.sql(''' + select sum(item.required_qty - item.transferred_qty) from `tabWork Order` pro, `tabWork Order Item` item where item.item_code = %s and item.parent = pro.name and pro.docstatus = 1 and item.source_warehouse = %s - and pro.status not in ("Stopped", "Completed")''', (self.item_code, self.warehouse))[0][0] + and pro.status not in ("Stopped", "Completed") + and item.required_qty > item.transferred_qty''', (self.item_code, self.warehouse))[0][0] self.set_projected_qty() @@ -123,7 +125,12 @@ class Bin(Document): and po.per_received < 100 """, (self.item_code))[0][0] - self.db_set('reserved_qty_for_sub_contract', (reserved_qty_for_sub_contract - materials_transferred)) + if reserved_qty_for_sub_contract > materials_transferred: + reserved_qty_for_sub_contract = reserved_qty_for_sub_contract - materials_transferred + else: + reserved_qty_for_sub_contract = 0 + + self.db_set('reserved_qty_for_sub_contract', reserved_qty_for_sub_contract) self.set_projected_qty() self.db_set('projected_qty', self.projected_qty) diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index d6db40d202..74dfa057aa 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -19,7 +19,7 @@ def get_product_bundle_items(item_code): where t2.new_item_code=%s and t1.parent = t2.name order by t1.idx""", item_code, as_dict=1) def get_packing_item_details(item): - return frappe.db.sql("""select item_name, description, stock_uom from `tabItem` + return frappe.db.sql("""select item_name, description, stock_uom, default_warehouse from `tabItem` where name = %s""", item, as_dict = 1)[0] def get_bin_qty(item, warehouse): @@ -28,7 +28,6 @@ def get_bin_qty(item, warehouse): return det and det[0] or frappe._dict() def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description): - bin = get_bin_qty(packing_item_code, main_item_row.warehouse) item = get_packing_item_details(packing_item_code) # check if exists @@ -48,15 +47,16 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip pi.description = item.description pi.uom = item.stock_uom pi.qty = flt(qty) - pi.actual_qty = flt(bin.get("actual_qty")) - pi.projected_qty = flt(bin.get("projected_qty")) pi.description = description if not pi.warehouse: - pi.warehouse = main_item_row.warehouse + pi.warehouse = item.default_warehouse or main_item_row.warehouse if not pi.batch_no: pi.batch_no = cstr(main_item_row.get("batch_no")) if not pi.target_warehouse: pi.target_warehouse = main_item_row.get("target_warehouse") + bin = get_bin_qty(packing_item_code, pi.warehouse) + pi.actual_qty = flt(bin.get("actual_qty")) + pi.projected_qty = flt(bin.get("projected_qty")) def make_packing_list(doc): """make packing list for Product Bundle item""" diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 3322d54558..98f15a831a 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -217,6 +217,12 @@ def validate_serial_no(sle, item_det): frappe.throw(_("Serial No {0} has already been received").format(serial_no), SerialNoDuplicateError) + if (sr.delivery_document_no and sle.voucher_type != 'Stock Entry' + and sle.voucher_type == sr.delivery_document_type): + return_against = frappe.db.get_value(sle.voucher_type, sle.voucher_no, 'return_against') + if return_against and return_against != sr.delivery_document_no: + frappe.throw(_("Serial no {0} has been already returned").format(sr.name)) + if sle.actual_qty < 0: if sr.warehouse!=sle.warehouse: frappe.throw(_("Serial No {0} does not belong to Warehouse {1}").format(serial_no, diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index c9d50f6d75..a14948142f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -141,8 +141,8 @@ frappe.ui.form.on('Stock Entry', { frm.trigger("toggle_display_account_head"); } - if (frm.doc.docstatus==1 && frm.doc.purpose == "Material Receipt") { - frm.add_custom_button(__('Make Retention Stock Entry'), function () { + if(frm.doc.docstatus==1 && frm.doc.purpose == "Material Receipt" && frm.get_sum('items', 'sample_quantity')) { + frm.add_custom_button(__('Make Sample Retention Stock Entry'), function () { frm.trigger("make_retention_stock_entry"); }); } @@ -500,7 +500,13 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ } this.frm.set_indicator_formatter('item_code', - function(doc) { return (doc.qty<=doc.actual_qty) ? "green" : "orange" }) + function(doc) { + if (!doc.s_warehouse) { + return 'blue'; + } else { + return (doc.qty<=doc.actual_qty) ? "green" : "orange" + } + }) this.frm.add_fetch("purchase_order", "supplier", "supplier");