Merge pull request #2275 from ankitjavalkarwork/fix2164

Add Delivery Qty to Sales Invoice From Delivery Note, Misc fixes
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 352dfab..5201e5e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -131,8 +131,10 @@
 				'keyword':'Delivered',
 				'second_source_dt': 'Delivery Note Item',
 				'second_source_field': 'qty',
-				'second_join_field': 'prevdoc_detail_docname',
-				'overflow_type': 'delivery'
+				'second_join_field': 'so_detail',
+				'overflow_type': 'delivery',
+				'extra_cond': """ and exists(select name from `tabSales Invoice` 
+					where name=`tabSales Invoice Item`.parent and ifnull(update_stock, 0) = 1)"""
 			})
 
 	def get_portal_page(self):
@@ -627,9 +629,11 @@
 		"Sales Invoice Item": {
 			"doctype": "Delivery Note Item",
 			"field_map": {
-				"name": "prevdoc_detail_docname",
+				"name": "si_detail",
 				"parent": "against_sales_invoice",
-				"serial_no": "serial_no"
+				"serial_no": "serial_no",
+				"sales_order": "against_sales_order",
+				"so_detail": "so_detail"
 			},
 			"postprocess": update_item
 		},
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index d173abe..5d77814 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -334,8 +334,8 @@
 				# But in this case reserved qty should only be reduced by 10 and not 12
 
 				already_delivered_qty = self.get_already_delivered_qty(self.name,
-					d.against_sales_order, d.prevdoc_detail_docname)
-				so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname)
+					d.against_sales_order, d.so_detail)
+				so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.so_detail)
 
 				if already_delivered_qty + d.qty > so_qty:
 					reserved_qty_for_main_item = -(so_qty - already_delivered_qty)
@@ -377,7 +377,7 @@
 
 	def get_already_delivered_qty(self, dn, so, so_detail):
 		qty = frappe.db.sql("""select sum(qty) from `tabDelivery Note Item`
-			where prevdoc_detail_docname = %s and docstatus = 1
+			where so_detail = %s and docstatus = 1
 			and against_sales_order = %s
 			and parent != %s""", (so_detail, so, dn))
 		return qty and flt(qty[0][0]) or 0.0
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 9825b04..247d4ff 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -153,16 +153,21 @@
 					args['second_source_condition'] = ""
 					if args.get('second_source_dt') and args.get('second_source_field') \
 							and args.get('second_join_field'):
+						if not args.get("second_source_extra_cond"): 
+							args["second_source_extra_cond"] = ""
+
 						args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
 							from `tab%(second_source_dt)s`
 							where `%(second_join_field)s`="%(detail_id)s"
-							and (docstatus=1)), 0)""" % args
+							and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s), 0) """ % args
 
 					if args['detail_id']:
+						if not args.get("extra_cond"): args["extra_cond"] = ""
+
 						frappe.db.sql("""update `tab%(target_dt)s`
 							set %(target_field)s = (select sum(%(source_field)s)
 								from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s"
-								and (docstatus=1 %(cond)s)) %(second_source_condition)s
+								and (docstatus=1 %(cond)s) %(extra_cond)s) %(second_source_condition)s
 							where name='%(detail_id)s'""" % args)
 
 			# get unique transactions to update
@@ -171,12 +176,13 @@
 					args['name'] = name
 
 					# update percent complete in the parent table
-					frappe.db.sql("""update `tab%(target_parent_dt)s`
-						set %(target_parent_field)s = (select sum(if(%(target_ref_field)s >
-							ifnull(%(target_field)s, 0), %(target_field)s,
-							%(target_ref_field)s))/sum(%(target_ref_field)s)*100
-							from `tab%(target_dt)s` where parent="%(name)s") %(modified_cond)s
-						where name='%(name)s'""" % args)
+					if args.get('target_parent_field'):
+						frappe.db.sql("""update `tab%(target_parent_dt)s`
+							set %(target_parent_field)s = (select sum(if(%(target_ref_field)s >
+								ifnull(%(target_field)s, 0), %(target_field)s,
+								%(target_ref_field)s))/sum(%(target_ref_field)s)*100
+								from `tab%(target_dt)s` where parent="%(name)s") %(modified_cond)s
+							where name='%(name)s'""" % args)
 
 					# update field
 					if args.get('status_field'):
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 52dd66c..1a45c59 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -84,3 +84,4 @@
 erpnext.patches.v4_2.seprate_manufacture_and_repack
 erpnext.patches.v4_2.party_model
 erpnext.patches.v5_0.update_frozen_accounts_permission_role
+erpnext.patches.v5_0.update_dn_against_doc_fields
diff --git a/erpnext/patches/v5_0/update_dn_against_doc_fields.py b/erpnext/patches/v5_0/update_dn_against_doc_fields.py
new file mode 100644
index 0000000..e8780a7
--- /dev/null
+++ b/erpnext/patches/v5_0/update_dn_against_doc_fields.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+
+def execute():
+	frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
+
+	frappe.db.sql("""update `tabDelivery Note Item` set so_detail = prevdoc_detail_docname
+		where ifnull(against_sales_order, '') != ''""")
+
+	frappe.db.sql("""update `tabDelivery Note Item` set si_detail = prevdoc_detail_docname
+		where ifnull(against_sales_invoice, '') != ''""")
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index b24d297..e59d209 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -294,7 +294,7 @@
 			"doctype": "Delivery Note Item",
 			"field_map": {
 				"rate": "rate",
-				"name": "prevdoc_detail_docname",
+				"name": "so_detail",
 				"parent": "against_sales_order",
 			},
 			"postprocess": update_item,
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index c7ec893..f872292 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -34,12 +34,10 @@
 		self.assertRaises(frappe.ValidationError, make_delivery_note,
 			so.name)
 
-		sales_order = frappe.get_doc("Sales Order", so.name)
-		sales_order.submit()
-		dn = make_delivery_note(so.name)
+		dn = self.make_next_doc_testcase(so, "Delivery Note")
 
 		self.assertEquals(dn.doctype, "Delivery Note")
-		self.assertEquals(len(dn.get("delivery_note_details")), len(sales_order.get("sales_order_details")))
+		self.assertEquals(len(dn.get("delivery_note_details")), len(so.get("sales_order_details")))
 
 	def test_make_sales_invoice(self):
 		from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
@@ -49,22 +47,77 @@
 		self.assertRaises(frappe.ValidationError, make_sales_invoice,
 			so.name)
 
-		sales_order = frappe.get_doc("Sales Order", so.name)
-		sales_order.submit()
-		si = make_sales_invoice(so.name)
+		si = self.make_next_doc_testcase(so, "Sales Invoice")
 
 		self.assertEquals(si.doctype, "Sales Invoice")
-		self.assertEquals(len(si.get("entries")), len(sales_order.get("sales_order_details")))
+		self.assertEquals(len(si.get("entries")), len(so.get("sales_order_details")))
 		self.assertEquals(len(si.get("entries")), 1)
 
-		si.debit_to = "_Test Receivable - _TC"
-		si.posting_date = "2013-10-10"
+		si.set("debit_to", "_Test Receivable - _TC")
+		si.set("posting_date", "2013-10-10")
 		si.insert()
 		si.submit()
 
-		si1 = make_sales_invoice(so.name)
+		si1 = self.make_next_doc_testcase(so, "Sales Invoice")
 		self.assertEquals(len(si1.get("entries")), 0)
 
+	def test_update_qty(self):
+		so = frappe.copy_doc(test_records[0]).insert()
+
+		dn = self.make_next_doc_testcase(so, "Delivery Note")
+
+		dn.get("delivery_note_details")[0].qty = 6
+		dn.posting_date = "2013-10-10"
+		dn.insert()
+
+		delivery_note = frappe.get_doc("Delivery Note", dn.name)
+		delivery_note.submit()
+
+		sales_order = frappe.get_doc("Sales Order", so.name)
+
+		self.assertEquals(sales_order.get("sales_order_details")[0].delivered_qty, 6)
+
+		#Check delivered_qty after make_sales_invoice without update_stock checked
+		si1 = self.make_next_doc_testcase(sales_order, "Sales Invoice")
+
+		si1.set("debit_to", "_Test Receivable - _TC")
+		si1.set("posting_date", "2013-10-10")
+		si1.get("entries")[0].qty = 1
+		si1.insert()
+		si1.submit()
+
+		sales_order = frappe.get_doc("Sales Order", sales_order.name)
+
+		self.assertEquals(sales_order.get("sales_order_details")[0].delivered_qty, 6)
+
+		#Check delivered_qty after make_sales_invoice with update_stock checked
+		si2 = self.make_next_doc_testcase(sales_order, "Sales Invoice")
+
+		si2.set("debit_to", "_Test Receivable - _TC")
+		si2.set("posting_date", "2013-10-10")
+		si2.set("update_stock", 1)
+		si2.get("entries")[0].qty = 3
+		si2.insert()
+		si2.submit()
+
+		sales_order = frappe.get_doc("Sales Order", sales_order.name)
+
+		self.assertEquals(sales_order.get("sales_order_details")[0].delivered_qty, 9)
+
+	def make_next_doc_testcase(self, so, next_doc = None):
+
+		if so.docstatus < 1:
+			so.submit()
+
+		if next_doc == "Delivery Note":
+			from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
+			next_doc = make_delivery_note(so.name)
+
+		if next_doc == "Sales Invoice":
+			from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
+			next_doc = make_sales_invoice(so.name)
+		
+		return next_doc
 
 	def create_so(self, so_doc = None):
 		if not so_doc:
@@ -85,7 +138,7 @@
 		dn = frappe.get_doc(frappe.copy_doc(dn_test_records[0]))
 		dn.get("delivery_note_details")[0].item_code = so.get("sales_order_details")[0].item_code
 		dn.get("delivery_note_details")[0].against_sales_order = so.name
-		dn.get("delivery_note_details")[0].prevdoc_detail_docname = so.get("sales_order_details")[0].name
+		dn.get("delivery_note_details")[0].so_detail = so.get("sales_order_details")[0].name
 		if delivered_qty:
 			dn.get("delivery_note_details")[0].qty = delivered_qty
 		dn.insert()
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index ee8dc0c..67a33c9 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -25,7 +25,7 @@
 		self.status_updater = [{
 			'source_dt': 'Delivery Note Item',
 			'target_dt': 'Sales Order Item',
-			'join_field': 'prevdoc_detail_docname',
+			'join_field': 'so_detail',
 			'target_field': 'delivered_qty',
 			'target_parent_dt': 'Sales Order',
 			'target_parent_field': 'per_delivered',
@@ -34,6 +34,22 @@
 			'percent_join_field': 'against_sales_order',
 			'status_field': 'delivery_status',
 			'keyword': 'Delivered',
+			'second_source_dt': 'Sales Invoice Item',
+			'second_source_field': 'qty',
+			'second_join_field': 'so_detail',
+			'overflow_type': 'delivery',
+			'second_source_extra_cond': """ and exists(select name from `tabSales Invoice` 
+				where name=`tabSales Invoice Item`.parent and ifnull(update_stock, 0) = 1)"""
+		},
+		{
+			'source_dt': 'Delivery Note Item',
+			'target_dt': 'Sales Invoice Item',
+			'join_field': 'si_detail',
+			'target_field': 'delivered_qty',
+			'target_parent_dt': 'Sales Invoice',
+			'target_ref_field': 'qty',
+			'source_field': 'qty',
+			'percent_join_field': 'against_sales_invoice',
 			'overflow_type': 'delivery'
 		}]
 
@@ -113,7 +129,7 @@
 				if cint(frappe.defaults.get_global_default('maintain_same_sales_rate')):
 					super(DeliveryNote, self).validate_with_previous_doc(self.tname, {
 						fn[0] + " Item": {
-							"ref_dn_field": "prevdoc_detail_docname",
+							"ref_dn_field": "so_detail",
 							"compare_fields": [["rate", "="]],
 							"is_child_table": True
 						}
@@ -312,7 +328,7 @@
 			"field_map": {
 				"name": "dn_detail",
 				"parent": "delivery_note",
-				"prevdoc_detail_docname": "so_detail",
+				"so_detail": "so_detail",
 				"against_sales_order": "sales_order",
 				"serial_no": "serial_no"
 			},
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index a5fe469..57adf3f 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -373,11 +373,11 @@
    "read_only": 1
   }, 
   {
-   "fieldname": "prevdoc_detail_docname", 
+   "fieldname": "so_detail", 
    "fieldtype": "Data", 
    "hidden": 1, 
    "in_filter": 1, 
-   "label": "Against Document Detail No", 
+   "label": "Against Sales Order Item", 
    "no_copy": 1, 
    "oldfieldname": "prevdoc_detail_docname", 
    "oldfieldtype": "Data", 
@@ -389,6 +389,18 @@
    "width": "150px"
   }, 
   {
+   "fieldname": "si_detail", 
+   "fieldtype": "Data", 
+   "hidden": 1, 
+   "in_filter": 1, 
+   "label": "Against Sales Invoice Item", 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "read_only": 1
+  }, 
+  {
    "fieldname": "installed_qty", 
    "fieldtype": "Float", 
    "label": "Installed Qty", 
@@ -426,7 +438,7 @@
  ], 
  "idx": 1, 
  "istable": 1, 
- "modified": "2014-09-09 05:35:37.460939", 
+ "modified": "2014-10-08 11:11:59.411329", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Delivery Note Item",