diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 14bf9d57a1b..f6d4eee5186 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -263,7 +263,7 @@ class AccountsController(TransactionBase): if self.get("is_subcontracted"): args["is_subcontracted"] = self.is_subcontracted - ret = get_item_details(args, self) + ret = get_item_details(args, self, overwrite_warehouse=False) for fieldname, value in ret.items(): if item.meta.get_field(fieldname) and value is not None: diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index b79a2925e05..2dc3788568c 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -568,7 +568,7 @@ def make_project(source_name, target_doc=None): return doc @frappe.whitelist() -def make_delivery_note(source_name, target_doc=None): +def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False): def set_missing_values(source, target): target.ignore_pricing_rule = 1 target.run_method("set_missing_values") @@ -593,23 +593,13 @@ def make_delivery_note(source_name, target_doc=None): or item.get("buying_cost_center") \ or item_group.get("buying_cost_center") - target_doc = get_mapped_doc("Sales Order", source_name, { + mapper = { "Sales Order": { "doctype": "Delivery Note", "validation": { "docstatus": ["=", 1] } }, - "Sales Order Item": { - "doctype": "Delivery Note Item", - "field_map": { - "rate": "rate", - "name": "so_detail", - "parent": "against_sales_order", - }, - "postprocess": update_item, - "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1 - }, "Sales Taxes and Charges": { "doctype": "Sales Taxes and Charges", "add_if_empty": True @@ -618,7 +608,21 @@ def make_delivery_note(source_name, target_doc=None): "doctype": "Sales Team", "add_if_empty": True } - }, target_doc, set_missing_values) + } + + if not skip_item_mapping: + mapper["Sales Order Item"] = { + "doctype": "Delivery Note Item", + "field_map": { + "rate": "rate", + "name": "so_detail", + "parent": "against_sales_order", + }, + "postprocess": update_item, + "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1 + } + + target_doc = get_mapped_doc("Sales Order", source_name, mapper, target_doc, set_missing_values) return target_doc @@ -999,9 +1003,16 @@ def make_inter_company_purchase_order(source_name, target_doc=None): @frappe.whitelist() def make_pick_list(source_name, target_doc=None): + def update_item_quantity(source, target, source_parent): + target.qty = flt(source.qty) - flt(source.delivered_qty) + target.stock_qty = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.conversion_factor) + doc = get_mapped_doc("Sales Order", source_name, { "Sales Order": { "doctype": "Pick List", + "field_map": { + "doctype": "items_based_on" + }, "validation": { "docstatus": ["=", 1] } @@ -1009,11 +1020,11 @@ def make_pick_list(source_name, target_doc=None): "Sales Order Item": { "doctype": "Pick List Reference Item", "field_map": { - "item_code": "item", - "parenttype": "reference_doctype", - "parent": "reference_name", - "name": "reference_document_item" + "parent": "sales_order", + "name": "sales_order_item" }, + "postprocess": update_item_quantity, + "conditions": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1 }, }, target_doc) diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json index 3f96630faf7..c7a5fc8c750 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.json +++ b/erpnext/stock/doctype/pick_list/pick_list.json @@ -7,6 +7,7 @@ "field_order": [ "company", "column_break_4", + "items_based_on", "parent_warehouse", "section_break_4", "reference_items", @@ -50,9 +51,16 @@ "fieldtype": "Table", "label": "Items To Be Picked", "options": "Pick List Reference Item" + }, + { + "default": "Sales Order", + "fieldname": "items_based_on", + "fieldtype": "Select", + "label": "Items Based On", + "options": "\nSales Order\nWork Order" } ], - "modified": "2019-08-01 10:50:17.055509", + "modified": "2019-08-13 19:30:01.151720", "modified_by": "Administrator", "module": "Stock", "name": "Pick List", diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 77dacd5144d..20b42300029 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -5,7 +5,10 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document -from frappe.model.mapper import get_mapped_doc +from six import iteritems +from frappe.model.mapper import get_mapped_doc, map_child_doc +from frappe.utils import floor, flt, today +from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note as make_delivery_note_from_sales_order class PickList(Document): def set_item_locations(self): @@ -17,46 +20,56 @@ class PickList(Document): # Reset self.delete_key('item_locations') - for item in reference_items: - data = get_items_with_warehouse_and_quantity(item, from_warehouses) - for item_info in data: - print(self.append('item_locations', item_info)) + for item_doc in reference_items: + if frappe.get_cached_value('Item', item_doc.item_code, 'has_serial_no'): + item_locations = get_item_locations_based_on_serial_nos(item_doc) + elif frappe.get_cached_value('Item', item_doc.item_code, 'has_batch_no'): + item_locations = get_item_locations_based_on_batch_nos(item_doc) + else: + item_locations = get_items_with_warehouse_and_quantity(item_doc, from_warehouses) - for item_doc in self.get('item_locations'): - if frappe.get_cached_value('Item', item_doc.item, 'has_serial_no'): - set_serial_nos(item_doc) - elif frappe.get_cached_value('Item', item_doc.item, 'has_batch_no'): - set_batch_no(item_doc, self) + for row in item_locations: + row.update({ + 'item_code': item_doc.item_code, + 'sales_order': item_doc.sales_order, + 'sales_order_item': item_doc.sales_order_item, + 'uom': item_doc.uom, + 'stock_uom': item_doc.stock_uom, + 'conversion_factor': item_doc.conversion_factor, + 'stock_qty': row.get("qty", 0) * item_doc.conversion_factor, + 'picked_qty': row.get("qty", 0) * item_doc.conversion_factor + }) + self.append('item_locations', row) def get_items_with_warehouse_and_quantity(item_doc, from_warehouses): - items = [] - item_locations = get_available_items(item_doc.item, from_warehouses) - remaining_qty = item_doc.qty + item_locations = [] + item_location_map = get_available_items(item_doc.item_code, from_warehouses) + remaining_stock_qty = item_doc.stock_qty + while remaining_stock_qty > 0 and item_location_map: + item_location = item_location_map.pop(0) + stock_qty = remaining_stock_qty if item_location.qty >= remaining_stock_qty else item_location.qty + qty = stock_qty / (item_doc.conversion_factor or 1) - while remaining_qty > 0 and item_locations: - item_location = item_locations.pop(0) - qty = remaining_qty if item_location.qty >= remaining_qty else item_location.qty - items.append({ - 'item': item_doc.item, + uom_must_be_whole_number = frappe.db.get_value("UOM", item_doc.uom, "must_be_whole_number") + if uom_must_be_whole_number: + qty = floor(qty) + stock_qty = qty * item_doc.conversion_factor + + item_locations.append({ 'qty': qty, - 'warehouse': item_location.warehouse, - 'reference_doctype': item_doc.reference_doctype, - 'reference_name': item_doc.reference_name, - 'reference_document_item': item_doc.reference_document_item, + 'warehouse': item_location.warehouse }) - remaining_qty -= qty + remaining_stock_qty -= stock_qty - if remaining_qty: - frappe.msgprint('{} qty of {} is out of stock. Skipping...'.format(remaining_qty, item_doc.item)) - return items + if remaining_stock_qty: + frappe.msgprint('{0} {1} of {2} is not available.' + .format(remaining_stock_qty / item_doc.conversion_factor, item_doc.uom, item_doc.item_code)) + return item_locations - return items - -def get_available_items(item, from_warehouses): +def get_available_items(item_code, from_warehouses): # gets all items available in different warehouses - # FIFO filters = frappe._dict({ - 'item_code': item, + 'item_code': item_code, 'actual_qty': ['>', 0] }) if from_warehouses: @@ -71,79 +84,170 @@ def get_available_items(item, from_warehouses): def set_serial_nos(item_doc): serial_nos = frappe.get_all('Serial No', { - 'item_code': item_doc.item, + 'item_code': item_doc.item_code, 'warehouse': item_doc.warehouse - }, limit=item_doc.qty, order_by='purchase_date') + }, limit=item_doc.stock_qty, order_by='purchase_date') item_doc.set('serial_no', '\n'.join([serial_no.name for serial_no in serial_nos])) - # should we assume that all serialized item available in stock will have serial no? + # should we assume that all serialized item_code available in stock will have serial no? -def set_batch_no(item_doc, parent_doc): - batches = frappe.db.sql(""" +def get_item_locations_based_on_serial_nos(item_doc): + serial_nos = frappe.get_all('Serial No', + fields = ['name', 'warehouse'], + filters = { + 'item_code': item_doc.item_code, + 'warehouse': ['!=', ''] + }, limit=item_doc.stock_qty, order_by='purchase_date', as_list=1) + + remaining_stock_qty = flt(item_doc.stock_qty) - len(serial_nos) + if remaining_stock_qty: + frappe.msgprint('{0} {1} of {2} is not available.' + .format(remaining_stock_qty, item_doc.stock_uom, item_doc.item_code)) + + warehouse_serial_nos_map = frappe._dict() + for serial_no, warehouse in serial_nos: + warehouse_serial_nos_map.setdefault(warehouse, []).append(serial_no) + + item_locations = [] + for warehouse, serial_nos in iteritems(warehouse_serial_nos_map): + item_locations.append({ + 'qty': len(serial_nos), + 'warehouse': warehouse, + 'serial_no': '\n'.join(serial_nos) + }) + + return item_locations + +def get_item_locations_based_on_batch_nos(item_doc): + batch_qty = frappe.db.sql(""" SELECT - `batch_no`, - SUM(`actual_qty`) AS `qty` + sle.`warehouse`, + sle.`batch_no`, + SUM(sle.`actual_qty`) AS `qty` FROM - `tabStock Ledger Entry` + `tabStock Ledger Entry` sle, `tabBatch` batch WHERE - `item_code`=%(item_code)s - AND `warehouse`=%(warehouse)s + sle.batch_no = batch.name + and sle.`item_code`=%(item_code)s + and IFNULL(batch.expiry_date, '2200-01-01') > %(today)s GROUP BY `warehouse`, `batch_no`, `item_code` HAVING `qty` > 0 + ORDER BY IFNULL(batch.expiry_date, '2200-01-01') """, { - 'item_code': item_doc.item, - 'warehouse': item_doc.warehouse, + 'item_code': item_doc.item_code, + 'today': today() }, as_dict=1) + item_locations = [] required_qty = item_doc.qty - while required_qty > 0 and batches: - batch = batches.pop() - batch_expiry = frappe.get_value('Batch', batch.batch_no, 'expiry_date') - if batch_expiry and batch_expiry <= frappe.utils.getdate(): - frappe.msgprint('Skipping expired Batch {}'.format(batch.batch_no)) - continue - item_doc.batch_no = batch.batch_no - if batch.qty >= item_doc.qty: - required_qty = 0 - break + for d in batch_qty: + if d.qty > required_qty: + d.qty = required_qty else: - # split item if quantity of item in batch is less that required - # Look for another batch + required_qty -= d.qty + + item_locations.append(d) + + if required_qty <= 0: + break + + # required_qty = item_doc.qty + # while required_qty > 0 and batches: + # batch = batches.pop() + # batch_expiry = frappe.get_value('Batch', batch.batch_no, 'expiry_date') + # if batch_expiry and batch_expiry <= frappe.utils.getdate(): + # frappe.msgprint('Skipping expired Batch {}'.format(batch.batch_no)) + # continue + # item_doc.batch_no = batch.batch_no + # if batch.qty >= item_doc.qty: + # required_qty = 0 + # break + # else: + # # split item_code if quantity of item_code in batch is less that required + # # Look for another batch + + # required_qty -= batch.qty + # # set quantity of current item_code equal to batch quantity + # item_doc.set('qty', batch.qty) + # item_doc = parent_doc.append('items', { + # 'item_code': item_doc.item_code, + # 'qty': required_qty, + # 'warehouse': item_doc.warehouse, + # 'sales_order': item_doc.sales_order, + # 'sales_order_item': item_doc.sales_order_item, + # 'uom': item_doc.uom, + # 'stock_uom': item_doc.stock_uom, + # 'conversion_factor': item_doc.conversion_factor, + # 'stock_qty': qty * item_doc.conversion_factor, + # }) - required_qty -= batch.qty - # set quantity of current item equal to batch quantity - item_doc.set('qty', batch.qty) - item_doc = parent_doc.append('items', { - 'item': item_doc.item, - 'qty': required_qty, - 'warehouse': item_doc.warehouse, - 'reference_doctype': item_doc.reference_doctype, - 'reference_name': item_doc.reference_name, - 'reference_document_item': item_doc.reference_document_item, - }) if required_qty: - frappe.msgprint('No batches found for {} qty of {}. Skipping...'.format(required_qty, item_doc.item)) - parent_doc.remove(item_doc) + frappe.msgprint('No batches found for {} qty of {}.'.format(required_qty, item_doc.item_code)) + + return item_locations @frappe.whitelist() def make_delivery_note(source_name, target_doc=None): - target_doc = get_mapped_doc("Pick List", source_name, { - "Pick List": { - "doctype": "Delivery Note", - # "validation": { - # "docstatus": ["=", 1] - # } - }, - "Pick List Item": { + pick_list = frappe.get_doc('Pick List', source_name) + sales_orders = [d.sales_order for d in pick_list.item_locations] + sales_orders = set(sales_orders) + + delivery_note = None + for sales_order in sales_orders: + delivery_note = make_delivery_note_from_sales_order(sales_order, + delivery_note, skip_item_mapping=True) + + for location in pick_list.item_locations: + sales_order_item = frappe.get_cached_doc('Sales Order Item', location.sales_order_item) + item_table_mapper = { "doctype": "Delivery Note Item", "field_map": { - "item": "item_code", - "reference_docname": "against_sales_order", + "rate": "rate", + "name": "so_detail", + "parent": "against_sales_order", }, - }, - }, target_doc) + "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1 + } - return target_doc \ No newline at end of file + dn_item = map_child_doc(sales_order_item, delivery_note, item_table_mapper) + + if dn_item: + dn_item.warehouse = location.warehouse + dn_item.qty = location.qty + + update_delivery_note_item(sales_order_item, dn_item, delivery_note) + + set_delivery_note_missing_values(delivery_note) + + return delivery_note + + +def set_delivery_note_missing_values(target): + target.run_method("set_missing_values") + target.run_method("set_po_nos") + target.run_method("calculate_taxes_and_totals") + +def update_delivery_note_item(source, target, delivery_note): + cost_center = frappe.db.get_value("Project", delivery_note.project, "cost_center") + if not cost_center: + cost_center = frappe.db.get_value('Item Default', + fieldname=['buying_cost_center'], + filters={ + 'parent': source.item_code, + 'parenttype': 'Item', + 'company': delivery_note.company + }) + + if not cost_center: + cost_center = frappe.db.get_value('Item Default', + fieldname=['buying_cost_center'], + filters={ + 'parent': source.item_group, + 'parenttype': 'Item Group', + 'company': delivery_note.company + }) + + target.cost_center = cost_center \ No newline at end of file diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.json b/erpnext/stock/doctype/pick_list_item/pick_list_item.json index c83b6961444..9ee806acf52 100644 --- a/erpnext/stock/doctype/pick_list_item/pick_list_item.json +++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.json @@ -4,32 +4,29 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "item", + "item_code", "item_name", "column_break_2", "description", - "has_batch_no", - "has_serial_no", "section_break_5", "warehouse", + "quantity_section", "qty", + "stock_qty", "picked_qty", + "column_break_11", + "uom", + "stock_uom", + "conversion_factor", + "serial_no_and_batch_section", "serial_no", + "column_break_20", "batch_no", - "reference_section", - "reference_doctype", - "reference_name", - "reference_document_item" + "column_break_15", + "sales_order", + "sales_order_item" ], "fields": [ - { - "fieldname": "item", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Item", - "options": "Item", - "read_only": 1 - }, { "fieldname": "qty", "fieldtype": "Float", @@ -52,72 +49,31 @@ "read_only": 1 }, { - "fetch_from": "item.item_name", + "fetch_from": "item_code.item_name", "fieldname": "item_name", "fieldtype": "Data", "label": "Item Name", "read_only": 1 }, { - "fetch_from": "item.description", + "fetch_from": "item_code.description", "fieldname": "description", "fieldtype": "Text", "label": "Description", "read_only": 1 }, { - "fieldname": "reference_document_item", - "fieldtype": "Data", - "label": "Reference Document Item", - "read_only": 1 - }, - { + "depends_on": "serial_no", "fieldname": "serial_no", "fieldtype": "Small Text", - "label": "Serial No", - "read_only": 1 + "label": "Serial No" }, { + "depends_on": "batch_no", "fieldname": "batch_no", "fieldtype": "Link", "label": "Batch No", - "options": "Batch", - "read_only": 1 - }, - { - "default": "0", - "fetch_from": "item.has_serial_no", - "fieldname": "has_serial_no", - "fieldtype": "Check", - "label": "Has Serial No", - "read_only": 1 - }, - { - "default": "0", - "fetch_from": "item.has_batch_no", - "fieldname": "has_batch_no", - "fieldtype": "Check", - "label": "Has Batch No", - "read_only": 1 - }, - { - "fieldname": "reference_section", - "fieldtype": "Section Break", - "label": "Reference" - }, - { - "fieldname": "reference_doctype", - "fieldtype": "Select", - "label": "Reference Document Type", - "options": "Sales Order\nWork Order", - "read_only": 1 - }, - { - "fieldname": "reference_name", - "fieldtype": "Dynamic Link", - "label": "Reference Document", - "options": "reference_doctype", - "read_only": 1 + "options": "Batch" }, { "fieldname": "column_break_2", @@ -126,10 +82,80 @@ { "fieldname": "section_break_5", "fieldtype": "Section Break" + }, + { + "fieldname": "stock_uom", + "fieldtype": "Link", + "label": "Stock UOM", + "options": "UOM", + "read_only": 1 + }, + { + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, + { + "fieldname": "uom", + "fieldtype": "Link", + "label": "UOM", + "options": "UOM", + "read_only": 1 + }, + { + "fieldname": "conversion_factor", + "fieldtype": "Float", + "label": "UOM Conversion Factor", + "read_only": 1 + }, + { + "fieldname": "stock_qty", + "fieldtype": "Float", + "label": "Qty as per Stock UOM", + "read_only": 1 + }, + { + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item", + "options": "Item", + "read_only": 1 + }, + { + "fieldname": "quantity_section", + "fieldtype": "Section Break", + "label": "Quantity" + }, + { + "fieldname": "column_break_15", + "fieldtype": "Section Break", + "label": "Reference" + }, + { + "fieldname": "sales_order", + "fieldtype": "Link", + "label": "Sales Order", + "options": "Sales Order", + "read_only": 1 + }, + { + "fieldname": "sales_order_item", + "fieldtype": "Data", + "label": "Sales Order Item", + "read_only": 1 + }, + { + "fieldname": "serial_no_and_batch_section", + "fieldtype": "Section Break", + "label": "Serial No and Batch" + }, + { + "fieldname": "column_break_20", + "fieldtype": "Column Break" } ], "istable": 1, - "modified": "2019-07-30 23:47:53.566473", + "modified": "2019-08-14 18:41:37.727388", "modified_by": "Administrator", "module": "Stock", "name": "Pick List Item", diff --git a/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json b/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json index 23ef2553a26..0aa94feb373 100644 --- a/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json +++ b/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json @@ -4,32 +4,19 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "item", + "item_code", + "quantity_section", "qty", - "reference_doctype", - "reference_name", - "reference_document_item" + "stock_qty", + "column_break_5", + "uom", + "stock_uom", + "conversion_factor", + "reference_section", + "sales_order", + "sales_order_item" ], "fields": [ - { - "fieldname": "item", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Item", - "options": "Item" - }, - { - "fieldname": "reference_doctype", - "fieldtype": "Link", - "label": "Reference Document type", - "options": "DocType" - }, - { - "fieldname": "reference_name", - "fieldtype": "Dynamic Link", - "label": "Reference Name", - "options": "reference_doctype" - }, { "fieldname": "qty", "fieldtype": "Float", @@ -37,13 +24,62 @@ "label": "Qty" }, { - "fieldname": "reference_document_item", + "fieldname": "quantity_section", + "fieldtype": "Section Break", + "label": "Quantity" + }, + { + "fieldname": "stock_qty", + "fieldtype": "Float", + "label": "Stock Qty" + }, + { + "fieldname": "uom", + "fieldtype": "Link", + "label": "UOM", + "options": "UOM" + }, + { + "fieldname": "stock_uom", + "fieldtype": "Link", + "label": "Stock UOM", + "options": "UOM" + }, + { + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item", + "options": "Item" + }, + { + "fieldname": "column_break_5", + "fieldtype": "Column Break" + }, + { + "fieldname": "reference_section", + "fieldtype": "Section Break", + "label": "Reference" + }, + { + "fieldname": "sales_order", + "fieldtype": "Link", + "label": "Sales Order", + "options": "Sales Order" + }, + { + "fieldname": "sales_order_item", "fieldtype": "Data", - "label": "Reference Document Item" + "label": "Sales Order Item" + }, + { + "fieldname": "conversion_factor", + "fieldtype": "Float", + "label": "UOM Conversion Factor" } ], "istable": 1, - "modified": "2019-07-30 23:43:30.901151", + "modified": "2019-08-14 18:38:28.867113", "modified_by": "Administrator", "module": "Stock", "name": "Pick List Reference Item", diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index f1d784c8d9e..41101f46780 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -22,7 +22,7 @@ sales_doctypes = ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice'] purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice'] @frappe.whitelist() -def get_item_details(args, doc=None): +def get_item_details(args, doc=None, overwrite_warehouse=True): """ args = { "item_code": "", @@ -44,11 +44,15 @@ def get_item_details(args, doc=None): "set_warehouse": "" } """ + args = process_args(args) + print('warehouse', args.warehouse, '========') item = frappe.get_cached_doc("Item", args.item_code) validate_item_details(args, item) - out = get_basic_details(args, item) + out = get_basic_details(args, item, overwrite_warehouse) + + print('warehouse2', out.warehouse, '========') get_item_tax_template(args, item, out) out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \ @@ -178,7 +182,7 @@ def validate_item_details(args, item): throw(_("Item {0} must be a Sub-contracted Item").format(item.name)) -def get_basic_details(args, item): +def get_basic_details(args, item, overwrite_warehouse=True): """ :param args: { "item_code": "", @@ -225,14 +229,26 @@ def get_basic_details(args, item): item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - warehouse = (args.get("set_warehouse") or item_defaults.get("default_warehouse") or - item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or args.warehouse) + if overwrite_warehouse or not args.warehouse: + warehouse = ( + args.get("set_warehouse") or + item_defaults.get("default_warehouse") or + item_group_defaults.get("default_warehouse") or + brand_defaults.get("default_warehouse") or + args.warehouse + ) - if not warehouse: - defaults = frappe.defaults.get_defaults() or {} - if defaults.get("default_warehouse") and frappe.db.exists("Warehouse", - {'name': defaults.default_warehouse, 'company': args.company}): - warehouse = defaults.default_warehouse + if not warehouse: + defaults = frappe.defaults.get_defaults() or {} + warehouse_exists = frappe.db.exists("Warehouse", { + 'name': defaults.default_warehouse, + 'company': args.company + }) + if defaults.get("default_warehouse") and warehouse_exists: + warehouse = defaults.default_warehouse + + else: + warehouse = args.warehouse if args.get('doctype') == "Material Request" and not args.get('material_request_type'): args['material_request_type'] = frappe.db.get_value('Material Request', @@ -784,6 +800,7 @@ def get_projected_qty(item_code, warehouse): @frappe.whitelist() def get_bin_details(item_code, warehouse): + print(item_code, warehouse, '---------------------------') return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, ["projected_qty", "actual_qty", "reserved_qty"], as_dict=True, cache=True) \ or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0}