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