From 54465f5df1adbfd6157c7d62fb3af360224669d7 Mon Sep 17 00:00:00 2001 From: pawan Date: Wed, 29 Nov 2017 10:18:38 +0530 Subject: [PATCH] review comments changes --- .../doctype/purchase_order/purchase_order.py | 12 +- .../purchase_order_item_supplied.json | 113 +++++++++++++++++- erpnext/controllers/buying_controller.py | 4 + erpnext/stock/doctype/bin/bin.py | 59 ++++++--- .../stock/doctype/stock_entry/stock_entry.py | 21 +--- 5 files changed, 164 insertions(+), 45 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 038683090b..6522a34a6e 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -202,6 +202,9 @@ class PurchaseOrder(BuyingController): if self.has_drop_ship_item(): self.update_delivered_qty_in_sales_order() + if self.is_subcontracted == "Yes": + self.update_reserved_qty_for_subcontract() + self.check_for_closed_status() frappe.db.set(self,'status','Cancelled') @@ -252,15 +255,10 @@ class PurchaseOrder(BuyingController): item.received_qty = item.qty def update_reserved_qty_for_subcontract(self): - items = list(set([d.rm_item_code for d in self.get("supplied_items")])) - item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse - from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) - for d in self.supplied_items: if d.rm_item_code: - warehouse = item_wh.get(d.rm_item_code) - stock_bin = get_bin(d.rm_item_code, warehouse) - stock_bin.update_reserved_qty_for_sub_contracting(self.name, transferred_qty=0, transaction_type = "Reserve") + stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse) + stock_bin.update_reserved_qty_for_sub_contracting() @frappe.whitelist() def close_or_unclose_purchase_orders(names, status): diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json index 4a870374ce..1bcf5e444b 100644 --- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json +++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -10,16 +11,20 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "main_item_code", "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": "Item Code", "length": 0, "no_copy": 0, @@ -29,6 +34,7 @@ "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, @@ -36,16 +42,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "rm_item_code", "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": "Raw Material Item Code", "length": 0, "no_copy": 0, @@ -55,6 +65,7 @@ "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, @@ -62,16 +73,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "required_qty", "fieldtype": "Float", "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": "Supplied Qty", "length": 0, "no_copy": 0, @@ -81,6 +96,7 @@ "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, @@ -88,16 +104,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "rate", "fieldtype": "Currency", "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": "Rate", "length": 0, "no_copy": 0, @@ -108,6 +128,7 @@ "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, @@ -115,16 +136,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "amount", "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Amount", "length": 0, "no_copy": 0, @@ -135,6 +160,7 @@ "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, @@ -142,16 +168,49 @@ "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": "bom_detail_no", "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": "BOM Detail No", "length": 0, "no_copy": 0, @@ -161,6 +220,7 @@ "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, @@ -168,16 +228,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "reference_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": "Reference Name", "length": 0, "no_copy": 0, @@ -187,6 +251,7 @@ "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, @@ -194,16 +259,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "conversion_factor", "fieldtype": "Float", "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Conversion Factor", "length": 0, "no_copy": 0, @@ -213,6 +282,7 @@ "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, @@ -220,16 +290,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "stock_uom", "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": "Stock Uom", "length": 0, "no_copy": 0, @@ -240,6 +314,39 @@ "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, + "default": "", + "fieldname": "reserve_warehouse", + "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": "Reserve Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "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, @@ -247,17 +354,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 1, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-07-11 03:28:05.533063", + "modified": "2017-11-29 08:51:08.362463", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item Supplied", @@ -266,5 +373,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/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index a31db6484c..5f762d50e1 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -160,6 +160,10 @@ class BuyingController(StockController): if item in self.sub_contracted_items and not item.bom: frappe.throw(_("Please select BOM in BOM field for Item {0}").format(item.item_code)) + for supplied_item in self.get("supplied_items"): + if not supplied_item.reserve_warehouse: + frappe.throw(_("Reserved Warehouse is mandatory for Item {0} in Raw Materials supplied").format(supplied_item.rm_item_code)) + else: for item in self.get("items"): if item.bom: diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index b3e89dc78d..efda055ccd 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -94,27 +94,48 @@ class Bin(Document): self.db_set('reserved_qty_for_production', self.reserved_qty_for_production) self.db_set('projected_qty', self.projected_qty) - def update_reserved_qty_for_sub_contracting(self, po_name, transferred_qty, transaction_type): - #Update Reserved Quantity for Sub Contracting in Bin - if transaction_type == "Reserve": - required_qty = frappe.db.sql('''select sum(itemsup.required_qty) - from `tabItem` item, `tabPurchase Order` po, `tabPurchase Order Item Supplied` itemsup - where - item.name = itemsup.rm_item_code - and po.name = %s - and itemsup.rm_item_code = %s - and itemsup.parent = po.name - and po.docstatus = 1 - and po.is_subcontracted = 'Yes' - and item.default_warehouse = %s''', (po_name, self.item_code, self.warehouse))[0][0] - elif transaction_type == "Transfer": - required_qty = 0 - - reserved_qty_bin = self.reserved_qty_for_sub_contract - reserved_qty_for_sub_contract = reserved_qty_bin + required_qty - transferred_qty + def update_reserved_qty_for_sub_contracting(self): + #reserved qty + reserved_qty_for_sub_contract = frappe.db.sql('''select ifnull(sum(itemsup.required_qty),0) + from `tabPurchase Order` po, `tabPurchase Order Item Supplied` itemsup + where + itemsup.rm_item_code = %s + and itemsup.parent = po.name + and po.docstatus = 1 + and po.is_subcontracted = 'Yes' + and itemsup.reserve_warehouse = %s''', (self.item_code, self.warehouse))[0][0] + #cancelled qty + reserved_qty_cancelled = frappe.db.sql('''select ifnull(sum(itemsup.required_qty),0) + from `tabPurchase Order` po, `tabPurchase Order Item Supplied` itemsup + where + itemsup.rm_item_code = %s + and itemsup.parent = po.name + and po.docstatus = 2 + and po.is_subcontracted = 'Yes' + and itemsup.reserve_warehouse = %s''', (self.item_code, self.warehouse))[0][0] + #Get Transferred Entries + materials_transferred = frappe.db.sql(""" + select + ifnull(sum(qty),0) + from + `tabStock Entry` se, `tabStock Entry Detail` sed + where + sed.item_code = %s and sed.s_warehouse = %s + and se.name = sed.parent and se.docstatus=1 and se.purpose='Subcontract' + and ifnull(se.purchase_order, '') !=''""", (self.item_code, self.warehouse))[0][0] + #Material Transfer Cancelled + materials_transfer_cancelled = frappe.db.sql(""" + select + ifnull(sum(qty),0) + from + `tabStock Entry` se, `tabStock Entry Detail` sed + where + sed.item_code = %s and sed.s_warehouse = %s + and se.name = sed.parent and se.docstatus=2 and se.purpose='Subcontract' + and ifnull(se.purchase_order, '') !=''""", (self.item_code, self.warehouse))[0][0] self.set_projected_qty() - self.db_set('reserved_qty_for_sub_contract', reserved_qty_for_sub_contract) + self.db_set('reserved_qty_for_sub_contract', (reserved_qty_for_sub_contract - reserved_qty_cancelled - materials_transferred + materials_transfer_cancelled)) self.db_set('projected_qty', self.projected_qty) def update_item_projected_qty(item_code): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 40e386ea67..e05ccc90f9 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -72,6 +72,8 @@ class StockEntry(StockController): def on_cancel(self): self.update_stock_ledger() self.update_production_order() + if self.purchase_order and self.purpose == "Subcontract": + self.update_purchase_order_supplied_items() self.make_gl_entries_on_cancel() def validate_purpose(self): @@ -807,28 +809,13 @@ class StockEntry(StockController): frappe.throw(_("Batch {0} of Item {1} has expired.").format(item.batch_no, item.item_code)) def update_purchase_order_supplied_items(self): - materials_transferred = frappe._dict(frappe.db.sql(""" - select - concat(item_code, sed.s_warehouse), sum(qty) - from - `tabStock Entry` se, `tabStock Entry Detail` sed - where - se.name = sed.parent and se.docstatus=1 and se.purpose='Subcontract' - and se.purchase_order= %s and ifnull(sed.s_warehouse, '') != '' - group by sed.item_code, sed.s_warehouse - """, self.purchase_order)) #Get PO Supplied Items Details po_doc = frappe.get_doc("Purchase Order",self.purchase_order) po_supplied_items = po_doc.get("supplied_items") - items = list(set([d.rm_item_code for d in po_supplied_items])) - item_wh = frappe._dict(frappe.db.sql("""select item_code as "item_code", default_warehouse as "warehouse" - from tabItem where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) #Update reserved sub contracted quantity in bin based on Supplied Item Details for d in po_supplied_items: - warehouse = item_wh.get(d.rm_item_code) - transferred_qty = materials_transferred.get(d.rm_item_code + warehouse) - stock_bin = get_bin(d.rm_item_code, warehouse) - stock_bin.update_reserved_qty_for_sub_contracting(self.purchase_order, transferred_qty, transaction_type = "Transfer") + stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse) + stock_bin.update_reserved_qty_for_sub_contracting() @frappe.whitelist() def get_production_order_details(production_order):