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:
parent
e047de854b
commit
182f4def00
@ -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:
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
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
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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}
|
||||
|
Loading…
x
Reference in New Issue
Block a user