fix: Delivery note creation from pick list

- Changes in serial no and batch no seletion
- Changes in warehouse overrwite logic

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
Suraj Shetty 2019-08-16 08:16:22 +05:30
parent e047de854b
commit 182f4def00
7 changed files with 401 additions and 199 deletions

View File

@ -263,7 +263,7 @@ class AccountsController(TransactionBase):
if self.get("is_subcontracted"): if self.get("is_subcontracted"):
args["is_subcontracted"] = self.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(): for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and value is not None: if item.meta.get_field(fieldname) and value is not None:

View File

@ -568,7 +568,7 @@ def make_project(source_name, target_doc=None):
return doc return doc
@frappe.whitelist() @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): def set_missing_values(source, target):
target.ignore_pricing_rule = 1 target.ignore_pricing_rule = 1
target.run_method("set_missing_values") 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.get("buying_cost_center") \
or item_group.get("buying_cost_center") or item_group.get("buying_cost_center")
target_doc = get_mapped_doc("Sales Order", source_name, { mapper = {
"Sales Order": { "Sales Order": {
"doctype": "Delivery Note", "doctype": "Delivery Note",
"validation": { "validation": {
"docstatus": ["=", 1] "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": { "Sales Taxes and Charges": {
"doctype": "Sales Taxes and Charges", "doctype": "Sales Taxes and Charges",
"add_if_empty": True "add_if_empty": True
@ -618,7 +608,21 @@ def make_delivery_note(source_name, target_doc=None):
"doctype": "Sales Team", "doctype": "Sales Team",
"add_if_empty": True "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 return target_doc
@ -999,9 +1003,16 @@ def make_inter_company_purchase_order(source_name, target_doc=None):
@frappe.whitelist() @frappe.whitelist()
def make_pick_list(source_name, target_doc=None): 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, { doc = get_mapped_doc("Sales Order", source_name, {
"Sales Order": { "Sales Order": {
"doctype": "Pick List", "doctype": "Pick List",
"field_map": {
"doctype": "items_based_on"
},
"validation": { "validation": {
"docstatus": ["=", 1] "docstatus": ["=", 1]
} }
@ -1009,11 +1020,11 @@ def make_pick_list(source_name, target_doc=None):
"Sales Order Item": { "Sales Order Item": {
"doctype": "Pick List Reference Item", "doctype": "Pick List Reference Item",
"field_map": { "field_map": {
"item_code": "item", "parent": "sales_order",
"parenttype": "reference_doctype", "name": "sales_order_item"
"parent": "reference_name",
"name": "reference_document_item"
}, },
"postprocess": update_item_quantity,
"conditions": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
}, },
}, target_doc) }, target_doc)

View File

@ -7,6 +7,7 @@
"field_order": [ "field_order": [
"company", "company",
"column_break_4", "column_break_4",
"items_based_on",
"parent_warehouse", "parent_warehouse",
"section_break_4", "section_break_4",
"reference_items", "reference_items",
@ -50,9 +51,16 @@
"fieldtype": "Table", "fieldtype": "Table",
"label": "Items To Be Picked", "label": "Items To Be Picked",
"options": "Pick List Reference Item" "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", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Pick List", "name": "Pick List",

View File

@ -5,7 +5,10 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.model.document import Document 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): class PickList(Document):
def set_item_locations(self): def set_item_locations(self):
@ -17,46 +20,56 @@ class PickList(Document):
# Reset # Reset
self.delete_key('item_locations') self.delete_key('item_locations')
for item in reference_items: for item_doc in reference_items:
data = get_items_with_warehouse_and_quantity(item, from_warehouses) if frappe.get_cached_value('Item', item_doc.item_code, 'has_serial_no'):
for item_info in data: item_locations = get_item_locations_based_on_serial_nos(item_doc)
print(self.append('item_locations', item_info)) 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'): for row in item_locations:
if frappe.get_cached_value('Item', item_doc.item, 'has_serial_no'): row.update({
set_serial_nos(item_doc) 'item_code': item_doc.item_code,
elif frappe.get_cached_value('Item', item_doc.item, 'has_batch_no'): 'sales_order': item_doc.sales_order,
set_batch_no(item_doc, self) '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): def get_items_with_warehouse_and_quantity(item_doc, from_warehouses):
items = [] item_locations = []
item_locations = get_available_items(item_doc.item, from_warehouses) item_location_map = get_available_items(item_doc.item_code, from_warehouses)
remaining_qty = item_doc.qty 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: uom_must_be_whole_number = frappe.db.get_value("UOM", item_doc.uom, "must_be_whole_number")
item_location = item_locations.pop(0) if uom_must_be_whole_number:
qty = remaining_qty if item_location.qty >= remaining_qty else item_location.qty qty = floor(qty)
items.append({ stock_qty = qty * item_doc.conversion_factor
'item': item_doc.item,
item_locations.append({
'qty': qty, 'qty': qty,
'warehouse': item_location.warehouse, 'warehouse': item_location.warehouse
'reference_doctype': item_doc.reference_doctype,
'reference_name': item_doc.reference_name,
'reference_document_item': item_doc.reference_document_item,
}) })
remaining_qty -= qty remaining_stock_qty -= stock_qty
if remaining_qty: if remaining_stock_qty:
frappe.msgprint('{} qty of {} is out of stock. Skipping...'.format(remaining_qty, item_doc.item)) frappe.msgprint('{0} {1} of {2} is not available.'
return items .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_code, from_warehouses):
def get_available_items(item, from_warehouses):
# gets all items available in different warehouses # gets all items available in different warehouses
# FIFO
filters = frappe._dict({ filters = frappe._dict({
'item_code': item, 'item_code': item_code,
'actual_qty': ['>', 0] 'actual_qty': ['>', 0]
}) })
if from_warehouses: if from_warehouses:
@ -71,79 +84,170 @@ def get_available_items(item, from_warehouses):
def set_serial_nos(item_doc): def set_serial_nos(item_doc):
serial_nos = frappe.get_all('Serial No', { serial_nos = frappe.get_all('Serial No', {
'item_code': item_doc.item, 'item_code': item_doc.item_code,
'warehouse': item_doc.warehouse '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])) 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): def get_item_locations_based_on_serial_nos(item_doc):
batches = frappe.db.sql(""" 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 SELECT
`batch_no`, sle.`warehouse`,
SUM(`actual_qty`) AS `qty` sle.`batch_no`,
SUM(sle.`actual_qty`) AS `qty`
FROM FROM
`tabStock Ledger Entry` `tabStock Ledger Entry` sle, `tabBatch` batch
WHERE WHERE
`item_code`=%(item_code)s sle.batch_no = batch.name
AND `warehouse`=%(warehouse)s and sle.`item_code`=%(item_code)s
and IFNULL(batch.expiry_date, '2200-01-01') > %(today)s
GROUP BY GROUP BY
`warehouse`, `warehouse`,
`batch_no`, `batch_no`,
`item_code` `item_code`
HAVING `qty` > 0 HAVING `qty` > 0
ORDER BY IFNULL(batch.expiry_date, '2200-01-01')
""", { """, {
'item_code': item_doc.item, 'item_code': item_doc.item_code,
'warehouse': item_doc.warehouse, 'today': today()
}, as_dict=1) }, as_dict=1)
item_locations = []
required_qty = item_doc.qty required_qty = item_doc.qty
while required_qty > 0 and batches: for d in batch_qty:
batch = batches.pop() if d.qty > required_qty:
batch_expiry = frappe.get_value('Batch', batch.batch_no, 'expiry_date') d.qty = required_qty
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: else:
# split item if quantity of item in batch is less that required required_qty -= d.qty
# Look for another batch
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: if required_qty:
frappe.msgprint('No batches found for {} qty of {}. Skipping...'.format(required_qty, item_doc.item)) frappe.msgprint('No batches found for {} qty of {}.'.format(required_qty, item_doc.item_code))
parent_doc.remove(item_doc)
return item_locations
@frappe.whitelist() @frappe.whitelist()
def make_delivery_note(source_name, target_doc=None): def make_delivery_note(source_name, target_doc=None):
target_doc = get_mapped_doc("Pick List", source_name, { pick_list = frappe.get_doc('Pick List', source_name)
"Pick List": { sales_orders = [d.sales_order for d in pick_list.item_locations]
"doctype": "Delivery Note", sales_orders = set(sales_orders)
# "validation": {
# "docstatus": ["=", 1] delivery_note = None
# } for sales_order in sales_orders:
}, delivery_note = make_delivery_note_from_sales_order(sales_order,
"Pick List Item": { 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", "doctype": "Delivery Note Item",
"field_map": { "field_map": {
"item": "item_code", "rate": "rate",
"reference_docname": "against_sales_order", "name": "so_detail",
"parent": "against_sales_order",
}, },
}, "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
}, target_doc) }
return target_doc 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

View File

@ -4,32 +4,29 @@
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [ "field_order": [
"item", "item_code",
"item_name", "item_name",
"column_break_2", "column_break_2",
"description", "description",
"has_batch_no",
"has_serial_no",
"section_break_5", "section_break_5",
"warehouse", "warehouse",
"quantity_section",
"qty", "qty",
"stock_qty",
"picked_qty", "picked_qty",
"column_break_11",
"uom",
"stock_uom",
"conversion_factor",
"serial_no_and_batch_section",
"serial_no", "serial_no",
"column_break_20",
"batch_no", "batch_no",
"reference_section", "column_break_15",
"reference_doctype", "sales_order",
"reference_name", "sales_order_item"
"reference_document_item"
], ],
"fields": [ "fields": [
{
"fieldname": "item",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Item",
"options": "Item",
"read_only": 1
},
{ {
"fieldname": "qty", "fieldname": "qty",
"fieldtype": "Float", "fieldtype": "Float",
@ -52,72 +49,31 @@
"read_only": 1 "read_only": 1
}, },
{ {
"fetch_from": "item.item_name", "fetch_from": "item_code.item_name",
"fieldname": "item_name", "fieldname": "item_name",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Item Name", "label": "Item Name",
"read_only": 1 "read_only": 1
}, },
{ {
"fetch_from": "item.description", "fetch_from": "item_code.description",
"fieldname": "description", "fieldname": "description",
"fieldtype": "Text", "fieldtype": "Text",
"label": "Description", "label": "Description",
"read_only": 1 "read_only": 1
}, },
{ {
"fieldname": "reference_document_item", "depends_on": "serial_no",
"fieldtype": "Data",
"label": "Reference Document Item",
"read_only": 1
},
{
"fieldname": "serial_no", "fieldname": "serial_no",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"label": "Serial No", "label": "Serial No"
"read_only": 1
}, },
{ {
"depends_on": "batch_no",
"fieldname": "batch_no", "fieldname": "batch_no",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Batch No", "label": "Batch No",
"options": "Batch", "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
}, },
{ {
"fieldname": "column_break_2", "fieldname": "column_break_2",
@ -126,10 +82,80 @@
{ {
"fieldname": "section_break_5", "fieldname": "section_break_5",
"fieldtype": "Section Break" "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, "istable": 1,
"modified": "2019-07-30 23:47:53.566473", "modified": "2019-08-14 18:41:37.727388",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Pick List Item", "name": "Pick List Item",

View File

@ -4,32 +4,19 @@
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [ "field_order": [
"item", "item_code",
"quantity_section",
"qty", "qty",
"reference_doctype", "stock_qty",
"reference_name", "column_break_5",
"reference_document_item" "uom",
"stock_uom",
"conversion_factor",
"reference_section",
"sales_order",
"sales_order_item"
], ],
"fields": [ "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", "fieldname": "qty",
"fieldtype": "Float", "fieldtype": "Float",
@ -37,13 +24,62 @@
"label": "Qty" "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", "fieldtype": "Data",
"label": "Reference Document Item" "label": "Sales Order Item"
},
{
"fieldname": "conversion_factor",
"fieldtype": "Float",
"label": "UOM Conversion Factor"
} }
], ],
"istable": 1, "istable": 1,
"modified": "2019-07-30 23:43:30.901151", "modified": "2019-08-14 18:38:28.867113",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Pick List Reference Item", "name": "Pick List Reference Item",

View File

@ -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'] purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
@frappe.whitelist() @frappe.whitelist()
def get_item_details(args, doc=None): def get_item_details(args, doc=None, overwrite_warehouse=True):
""" """
args = { args = {
"item_code": "", "item_code": "",
@ -44,11 +44,15 @@ def get_item_details(args, doc=None):
"set_warehouse": "" "set_warehouse": ""
} }
""" """
args = process_args(args) args = process_args(args)
print('warehouse', args.warehouse, '========')
item = frappe.get_cached_doc("Item", args.item_code) item = frappe.get_cached_doc("Item", args.item_code)
validate_item_details(args, item) 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) 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 \ 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)) 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: { :param args: {
"item_code": "", "item_code": "",
@ -225,14 +229,26 @@ def get_basic_details(args, item):
item_group_defaults = get_item_group_defaults(item.name, args.company) item_group_defaults = get_item_group_defaults(item.name, args.company)
brand_defaults = get_brand_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 if overwrite_warehouse or not args.warehouse:
item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or 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: if not warehouse:
defaults = frappe.defaults.get_defaults() or {} defaults = frappe.defaults.get_defaults() or {}
if defaults.get("default_warehouse") and frappe.db.exists("Warehouse", warehouse_exists = frappe.db.exists("Warehouse", {
{'name': defaults.default_warehouse, 'company': args.company}): 'name': defaults.default_warehouse,
warehouse = 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'): if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
args['material_request_type'] = frappe.db.get_value('Material Request', args['material_request_type'] = frappe.db.get_value('Material Request',
@ -784,6 +800,7 @@ def get_projected_qty(item_code, warehouse):
@frappe.whitelist() @frappe.whitelist()
def get_bin_details(item_code, warehouse): def get_bin_details(item_code, warehouse):
print(item_code, warehouse, '---------------------------')
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
["projected_qty", "actual_qty", "reserved_qty"], as_dict=True, cache=True) \ ["projected_qty", "actual_qty", "reserved_qty"], as_dict=True, cache=True) \
or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0} or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0}