[Rename] Delivery Note Packing Item -> Packed Item
diff --git a/patches/october_2013/p06_rename_packing_list_doctype.py b/patches/october_2013/p06_rename_packing_list_doctype.py
new file mode 100644
index 0000000..a7a11e4
--- /dev/null
+++ b/patches/october_2013/p06_rename_packing_list_doctype.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes, os
+
+def execute():
+	webnotes.reload_doc("core", "doctype", "doctype")
+	
+	tables = webnotes.conn.sql_list("show tables")
+	
+	if "tabPacked Item" not in tables:
+		webnotes.rename_doc("DocType", "Delivery Note Packing Item", "Packed Item", force=True)
+	
+	webnotes.reload_doc("stock", "doctype", "packed_item")
+	
+	os.system("rm -rf app/stock/doctype/delivery_note_packing_item")
+	
+	if webnotes.conn.exists("DocType", "Delivery Note Packing Item"):
+			webnotes.delete_doc("DocType", "Delivery Note Packing Item")
\ No newline at end of file
diff --git a/stock/doctype/packed_item/__init__.py b/stock/doctype/packed_item/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stock/doctype/packed_item/__init__.py
diff --git a/stock/doctype/packed_item/packed_item.py b/stock/doctype/packed_item/packed_item.py
new file mode 100644
index 0000000..fc25958
--- /dev/null
+++ b/stock/doctype/packed_item/packed_item.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# MIT License. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+from webnotes.utils import cstr, flt
+from webnotes.model.doc import addchild
+from webnotes.model.bean import getlist
+
+class DocType:
+	def __init__(self, d, dl):
+		self.doc, self.doclist = d, dl
+		
+def get_sales_bom_items(item_code):
+	return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom 
+		from `tabSales BOM Item` t1, `tabSales BOM` t2 
+		where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1)
+
+def get_packing_item_details(item):
+	return webnotes.conn.sql("""select item_name, description, stock_uom from `tabItem` 
+		where name = %s""", item, as_dict = 1)[0]
+
+def get_bin_qty(item, warehouse):
+	det = webnotes.conn.sql("""select actual_qty, projected_qty from `tabBin` 
+		where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1)
+	return det and det[0] or ''
+
+def update_packing_list_item(obj, packing_item_code, qty, warehouse, line, packing_list_idx):
+	bin = get_bin_qty(packing_item_code, warehouse)
+	item = get_packing_item_details(packing_item_code)
+
+	# check if exists
+	exists = 0
+	for d in getlist(obj.doclist, 'packing_details'):
+		if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name:
+			pi, exists = d, 1
+			break
+
+	if not exists:
+		pi = addchild(obj.doc, 'packing_details', 'Packed Item', obj.doclist)
+
+	pi.parent_item = line.item_code
+	pi.item_code = packing_item_code
+	pi.item_name = item['item_name']
+	pi.parent_detail_docname = line.name
+	pi.description = item['description']
+	pi.uom = item['stock_uom']
+	pi.qty = flt(qty)
+	pi.actual_qty = bin and flt(bin['actual_qty']) or 0
+	pi.projected_qty = bin and flt(bin['projected_qty']) or 0
+	if not pi.warehouse:
+		pi.warehouse = warehouse
+	if not pi.batch_no:
+		pi.batch_no = cstr(line.batch_no)
+	pi.idx = packing_list_idx
+	
+	# saved, since this function is called on_update of delivery note
+	pi.save()
+	
+	packing_list_idx += 1
+
+
+def make_packing_list(obj, item_table_fieldname):
+	"""make packing list for sales bom item"""
+	packing_list_idx = 0
+	parent_items = []
+	for d in obj.doclist.get({"parentfield": item_table_fieldname}):
+		warehouse = (item_table_fieldname == "sales_order_details") \
+			and d.reserved_warehouse or d.warehouse
+		if webnotes.conn.get_value("Sales BOM", {"new_item_code": d.item_code}):
+			for i in get_sales_bom_items(d.item_code):
+				update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), 
+					warehouse, d, packing_list_idx)
+
+			if [d.item_code, d.name] not in parent_items:
+				parent_items.append([d.item_code, d.name])
+			
+	obj.doclist = cleanup_packing_list(obj, parent_items)
+	
+	return obj.doclist
+	
+def cleanup_packing_list(obj, parent_items):
+	"""Remove all those child items which are no longer present in main item table"""
+	delete_list = []
+	for d in obj.doclist.get({"parentfield": "packing_details"}):
+		if [d.parent_item, d.parent_detail_docname] not in parent_items:
+			# mark for deletion from doclist
+			delete_list.append(d.name)
+
+	if not delete_list:
+		return obj.doclist
+	
+	# delete from doclist
+	obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist))
+	
+	# delete from db
+	webnotes.conn.sql("""\
+		delete from `tabPacked Item`
+		where name in (%s)"""
+		% (", ".join(["%s"] * len(delete_list))),
+		tuple(delete_list))
+		
+	return obj.doclist
\ No newline at end of file
diff --git a/stock/doctype/packed_item/packed_item.txt b/stock/doctype/packed_item/packed_item.txt
new file mode 100644
index 0000000..8320502
--- /dev/null
+++ b/stock/doctype/packed_item/packed_item.txt
@@ -0,0 +1,170 @@
+[
+ {
+  "creation": "2013-02-22 01:28:00", 
+  "docstatus": 0, 
+  "modified": "2013-10-16 16:37:31", 
+  "modified_by": "Administrator", 
+  "owner": "Administrator"
+ }, 
+ {
+  "doctype": "DocType", 
+  "istable": 1, 
+  "module": "Stock", 
+  "name": "__common__"
+ }, 
+ {
+  "doctype": "DocField", 
+  "name": "__common__", 
+  "parent": "Packed Item", 
+  "parentfield": "fields", 
+  "parenttype": "DocType", 
+  "permlevel": 0
+ }, 
+ {
+  "doctype": "DocType", 
+  "name": "Packed Item"
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "parent_item", 
+  "fieldtype": "Link", 
+  "in_list_view": 1, 
+  "label": "Parent Item", 
+  "oldfieldname": "parent_item", 
+  "oldfieldtype": "Link", 
+  "options": "Item", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "item_code", 
+  "fieldtype": "Link", 
+  "in_filter": 1, 
+  "in_list_view": 1, 
+  "label": "Item Code", 
+  "oldfieldname": "item_code", 
+  "oldfieldtype": "Link", 
+  "options": "Item", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "item_name", 
+  "fieldtype": "Data", 
+  "in_filter": 1, 
+  "in_list_view": 1, 
+  "label": "Item Name", 
+  "oldfieldname": "item_name", 
+  "oldfieldtype": "Data", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "parent_detail_docname", 
+  "fieldtype": "Data", 
+  "hidden": 1, 
+  "in_list_view": 0, 
+  "label": "Parent Detail docname", 
+  "no_copy": 1, 
+  "oldfieldname": "parent_detail_docname", 
+  "oldfieldtype": "Data", 
+  "print_hide": 1, 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "description", 
+  "fieldtype": "Text", 
+  "in_list_view": 1, 
+  "label": "Description", 
+  "oldfieldname": "description", 
+  "oldfieldtype": "Text", 
+  "print_width": "300px", 
+  "read_only": 1, 
+  "width": "300px"
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "warehouse", 
+  "fieldtype": "Link", 
+  "in_list_view": 1, 
+  "label": "Warehouse", 
+  "oldfieldname": "warehouse", 
+  "oldfieldtype": "Link", 
+  "options": "Warehouse"
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "qty", 
+  "fieldtype": "Float", 
+  "in_list_view": 1, 
+  "label": "Qty", 
+  "oldfieldname": "qty", 
+  "oldfieldtype": "Currency", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "serial_no", 
+  "fieldtype": "Text", 
+  "label": "Serial No"
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "batch_no", 
+  "fieldtype": "Data", 
+  "label": "Batch No"
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "actual_qty", 
+  "fieldtype": "Float", 
+  "label": "Actual Qty", 
+  "no_copy": 1, 
+  "oldfieldname": "actual_qty", 
+  "oldfieldtype": "Currency", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "projected_qty", 
+  "fieldtype": "Float", 
+  "label": "Projected Qty", 
+  "no_copy": 1, 
+  "oldfieldname": "projected_qty", 
+  "oldfieldtype": "Currency", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "uom", 
+  "fieldtype": "Link", 
+  "label": "UOM", 
+  "oldfieldname": "uom", 
+  "oldfieldtype": "Link", 
+  "options": "UOM", 
+  "read_only": 1, 
+  "search_index": 0
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "prevdoc_doctype", 
+  "fieldtype": "Data", 
+  "hidden": 1, 
+  "label": "Prevdoc DocType", 
+  "oldfieldname": "prevdoc_doctype", 
+  "oldfieldtype": "Data", 
+  "print_hide": 1, 
+  "read_only": 1
+ }, 
+ {
+  "allow_on_submit": 1, 
+  "doctype": "DocField", 
+  "fieldname": "page_break", 
+  "fieldtype": "Check", 
+  "label": "Page Break", 
+  "oldfieldname": "page_break", 
+  "oldfieldtype": "Check", 
+  "read_only": 1
+ }
+]
\ No newline at end of file