completed sales purchase return as part of stock entry
diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py
index 229ec40..46c6ee4 100644
--- a/stock/doctype/delivery_note/delivery_note.py
+++ b/stock/doctype/delivery_note/delivery_note.py
@@ -133,7 +133,7 @@
 		super(DocType, self).validate()
 		
 		import utilities
-		utilities.validate_status(self.doc.status, ["Draft", "submitted", "Cancelled"])
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Cancelled"])
 
 		self.so_required()
 		self.validate_fiscal_year()
diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js
index 1581844..0b27d99 100644
--- a/stock/doctype/stock_entry/stock_entry.js
+++ b/stock/doctype/stock_entry/stock_entry.js
@@ -60,6 +60,7 @@
 	},
 	
 	refresh: function() {
+		var me = this;
 		erpnext.hide_naming_series();
 		this.toggle_related_fields(this.frm.doc);
 		this.toggle_enable_bom();
@@ -67,12 +68,13 @@
 			this.show_stock_ledger();
 		}
 		
-		if(this.frm.doc.docstatus === 1 && wn.boot.profile.can_create("Journal Voucher")) {
+		if(this.frm.doc.docstatus === 1 && 
+				wn.boot.profile.can_create.indexOf("Journal Voucher")!==-1) {
 			if(this.frm.doc.purpose === "Sales Return") {
-				this.frm.add_custom_button("Make Credit Note", this.make_return_jv);
+				this.frm.add_custom_button("Make Credit Note", function() { me.make_return_jv(); });
 				this.add_excise_button();
 			} else if(this.frm.doc.purpose === "Purchase Return") {
-				this.frm.add_custom_button("Make Debit Note", this.make_return_jv);
+				this.frm.add_custom_button("Make Debit Note", function() { me.make_return_jv(); });
 				this.add_excise_button();
 			}
 		}
@@ -172,8 +174,17 @@
 				stock_entry: this.frm.doc.name
 			},
 			callback: function(r) {
-				console.log(r);
-				loaddoc("Journal Voucher", r.message);
+				if(!r.exc) {
+					var jv_name = wn.model.make_new_doc_and_get_name('Journal Voucher');
+					var jv = locals["Journal Voucher"][jv_name];
+					$.extend(jv, r.message[0]);
+					$.each(r.message.slice(1), function(i, jvd) {
+						var child = wn.model.add_child(jv, "Journal Voucher Detail", "entries");
+						$.extend(child, jvd);
+					});
+					loaddoc("Journal Voucher", jv_name);
+				}
+				
 			}
 		});
 	},
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index dc67b9f..131e9ff 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -25,7 +25,6 @@
 from stock.utils import get_incoming_rate
 from stock.stock_ledger import get_previous_sle
 import json
-from accounts.utils import get_balance_on
 
 sql = webnotes.conn.sql
 
@@ -297,7 +296,7 @@
 			
 			# posting date check
 			ref_posting_datetime = "%s %s" % (cstr(ref.doclist[0].posting_date), 
-				cstr(ref.doclist[0].posting_time))
+				cstr(ref.doclist[0].posting_time) or "00:00:00")
 			this_posting_datetime = "%s %s" % (cstr(self.doc.posting_date), 
 				cstr(self.doc.posting_time))
 			if this_posting_datetime < ref_posting_datetime:
@@ -779,13 +778,30 @@
 		result = make_return_jv_from_purchase_receipt(se, ref)
 	
 	# create jv doclist and fetch balance for each unique row item
+	jv_list = [{
+		"__islocal": 1,
+		"doctype": "Journal Voucher",
+		"posting_date": se.doc.posting_date,
+		"voucher_type": se.doc.purpose == "Sales Return" and "Credit Note" or "Debit Note",
+		"fiscal_year": se.doc.fiscal_year,
+		"company": se.doc.company
+	}]
 	
-	if not webnotes.response.get("docs"):
-		webnotes.response["docs"] = []
-	
-	webnotes.response["docs"] = jv.doclist
-	
-	return jv.doc.name
+	from accounts.utils import get_balance_on
+	for r in result:
+		jv_list.append({
+			"__islocal": 1,
+			"doctype": "Journal Voucher Detail",
+			"parentfield": "entries",
+			"account": r.get("account"),
+			"debit": r.get("debit"),
+			"credit": r.get("credit"),
+			"against_invoice": r.get("against_invoice"),
+			"against_voucher": r.get("against_voucher"),
+			"balance": get_balance_on(r.get("account"), se.doc.posting_date)
+		})
+		
+	return jv_list
 	
 def make_return_jv_from_sales_invoice(se, ref):
 	# customer account entry
@@ -833,12 +849,10 @@
 		ref.doclist[0].name)
 	
 	if not invoices_against_delivery:
-		item_codes = [item.item_code for item in se.doclist.get({"parentfield": "mtn_details"})]
-		sales_orders_against_delivery = [d.prev_docname for d in 
-			ref.doclist.get({"prev_doctype": "Sales Order"}) 
-			if d.prev_docname and d.item_code in item_codes]
-
-		invoices_against_delivery = get_invoice_list("Sales Order Item", "sales_order",
+		sales_orders_against_delivery = [d.prevdoc_docname for d in 
+			ref.doclist.get({"prevdoc_doctype": "Sales Order"}) if d.prevdoc_docname]
+		
+		invoices_against_delivery = get_invoice_list("Sales Invoice Item", "sales_order",
 			sales_orders_against_delivery)
 	
 	against_invoice = {}
@@ -846,8 +860,10 @@
 	for se_item in se.doclist.get({"parentfield": "mtn_details"}):
 		pending = se_item.transfer_qty
 		for sales_invoice in invoices_against_delivery:
-			si_doclist = webnotes.get_doclist("Sales Invoice", sales_invoice)
-			ref_item = si_doclist.get({"item_code": se_item.item_code})
+			si = webnotes.bean("Sales Invoice", sales_invoice)
+			si.run_method("make_packing_list")
+			ref_item = si.doclist.get({"item_code": se_item.item_code})
+			
 			if not ref_item:
 				continue
 			
@@ -860,12 +876,12 @@
 				transfer_qty = pending
 				pending = 0
 			
-			account, debit = get_sales_account_and_amount_from_item(si_doclist, ref_item,
+			account, debit = get_sales_account_and_amount_from_item(si.doclist, ref_item,
 				transfer_qty)
 				
-			if si_doclist[0].name not in against_invoice:
+			if si.doclist[0].name not in against_invoice:
 				against_invoice[sales_invoice] = {
-					"parent": {"account": si_doclist[0].debit_to, "credit": 0},
+					"parent": {"account": si.doclist[0].debit_to, "credit": 0},
 					"children": {}
 				}
 				
@@ -883,17 +899,79 @@
 	
 	result = []
 	for sales_invoice, opts in against_invoice.items():
-		result += [opts["parent"]] + [{"account": account, "debit": debit} 
+		parent = opts["parent"]
+		parent.update({"against_invoice": sales_invoice})
+		children = [{"account": account, "debit": debit} 
 			for account, debit in opts["children"].items()]
+		result += [parent] + children
 	return result
 	
 def get_invoice_list(doctype, link_field, value):
 	if isinstance(value, basestring):
 		value = [value]
-		
+	
 	return webnotes.conn.sql_list("""select distinct parent from `tab%s`
 		where docstatus = 1 and `%s` in (%s)""" % (doctype, link_field,
 			", ".join(["%s"]*len(value))), tuple(value))
 			
 def make_return_jv_from_purchase_receipt(se, ref):
-	pass
+	invoice_against_receipt = get_invoice_list("Purchase Invoice Item", "purchase_receipt",
+		ref.doclist[0].name)
+	
+	if not invoice_against_receipt:
+		purchase_orders_against_receipt = [d.prevdoc_docname for d in 
+			ref.doclist.get({"prevdoc_doctype": "Purchase Order"}) if d.prevdoc_docname]
+		
+		invoice_against_receipt = get_invoice_list("Purchase Invoice Item", "purchase_order",
+			purchase_orders_against_receipt)
+			
+	against_voucher = {}
+	
+	for se_item in se.doclist.get({"parentfield": "mtn_details"}):
+		pending = se_item.transfer_qty
+		for purchase_invoice in invoice_against_receipt:
+			pi = webnotes.bean("Purchase Invoice", purchase_invoice)
+			ref_item = pi.doclist.get({"item_code": se_item.item_code})
+			
+			if not ref_item:
+				continue
+			
+			ref_item = ref_item[0]
+			
+			if ref_item.qty < pending:
+				transfer_qty = ref_item.qty
+				pending -= ref_item.qty
+			else:
+				transfer_qty = pending
+				pending = 0
+			
+			credit = ref_item.rate * transfer_qty
+			account = ref_item.expense_head
+			
+			if pi.doclist[0].name not in against_voucher:
+				against_voucher[purchase_invoice] = {
+					"parent": {"account": pi.doclist[0].credit_to, "debit": 0},
+					"children": {}
+				}
+			
+			against_voucher[purchase_invoice]["parent"]["debit"] += credit
+
+			if account not in against_voucher[purchase_invoice]["children"]:
+				against_voucher[purchase_invoice]["children"][account] = 0
+				
+			against_voucher[purchase_invoice]["children"][account] += credit
+			
+			# find tax account and value and add corresponding rows
+			
+			if pending <= 0:
+				break
+	
+	result = []
+	for purchase_invoice, opts in against_voucher.items():
+		parent = opts["parent"]
+		parent.update({"against_voucher": purchase_invoice})
+		children = [{"account": account, "credit": credit} 
+			for account, credit in opts["children"].items()]
+		result += [parent] + children
+	return result
+		
\ No newline at end of file
diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py
index c0f8f28..049b0e6 100644
--- a/stock/doctype/stock_entry/test_stock_entry.py
+++ b/stock/doctype/stock_entry/test_stock_entry.py
@@ -9,6 +9,9 @@
 	def test_auto_material_request(self):
 		webnotes.conn.sql("""delete from `tabMaterial Request Item`""")
 		webnotes.conn.sql("""delete from `tabMaterial Request`""")
+		self._clear_stock()
+		
+		webnotes.conn.set_value("Global Defaults", None, "auto_indent", True)
 
 		st1 = webnotes.bean(copy=test_records[0])
 		st1.insert()
@@ -166,9 +169,14 @@
 	
 	def _insert_material_receipt(self):
 		self._clear_stock()
-		material_receipt = webnotes.bean(copy=test_records[0])
-		material_receipt.insert()
-		material_receipt.submit()
+		se1 = webnotes.bean(copy=test_records[0])
+		se1.insert()
+		se1.submit()
+		
+		se2 = webnotes.bean(copy=test_records[0])
+		se2.doclist[1].item_code = "_Test Item Home Desktop 100"
+		se2.insert()
+		se2.submit()
 		
 	def _get_actual_qty(self):
 		return flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item", 
@@ -238,6 +246,8 @@
 		actual_qty_2 = self._get_actual_qty()
 		
 		self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
+		
+		return se
 	
 	def test_sales_invoice_return_of_non_packing_item(self):
 		self._test_sales_invoice_return("_Test Item", 5, 2)
@@ -248,11 +258,12 @@
 	def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty):
 		self._insert_material_receipt()
 		
-		actual_qty_0 = self._get_actual_qty()
-		
-		# insert and submit delivery note
 		from stock.doctype.delivery_note.test_delivery_note \
 			import test_records as delivery_note_test_records
+		
+		actual_qty_0 = self._get_actual_qty()
+		
+		# make a delivery note based on this invoice
 		dn = webnotes.bean(copy=delivery_note_test_records[0])
 		dn.doclist[1].item_code = item_code
 		dn.insert()
@@ -262,11 +273,26 @@
 		
 		self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
 		
+		si_doclist = webnotes.map_doclist([
+			["Delivery Note", "Sales Invoice"],
+			["Delivery Note Item", "Sales Invoice Item"],
+			["Sales Taxes and Charges", "Sales Taxes and Charges"],
+			["Sales Team", "Sales Team"]], dn.doc.name)
+			
+		si = webnotes.bean(si_doclist)
+		si.doc.posting_date = dn.doc.posting_date
+		si.doc.debit_to = "_Test Customer - _TC"
+		for d in si.doclist.get({"parentfield": "entries"}):
+			d.income_account = "Sales - _TC"
+			d.cost_center = "_Test Cost Center - _TC"
+		si.insert()
+		si.submit()
+		
 		# insert and submit stock entry for sales return
 		se = webnotes.bean(copy=test_records[0])
 		se.doc.purpose = "Sales Return"
 		se.doc.delivery_note_no = dn.doc.name
-		se.doc.posting_date = "2013-03-01"
+		se.doc.posting_date = "2013-03-10"
 		se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
 		
 		se.insert()
@@ -275,12 +301,115 @@
 		actual_qty_2 = self._get_actual_qty()
 		self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
 		
+		return se
+		
 	def test_delivery_note_return_of_non_packing_item(self):
 		self._test_delivery_note_return("_Test Item", 5, 2)
 		
 	def test_delivery_note_return_of_packing_item(self):
 		self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
 		
+	def _test_sales_return_jv(self, se, returned_value):
+		from stock.doctype.stock_entry.stock_entry import make_return_jv
+		jv_list = make_return_jv(se.doc.name)
+		
+		self.assertEqual(len(jv_list), 3)
+		self.assertEqual(jv_list[0].get("voucher_type"), "Credit Note")
+		self.assertEqual(jv_list[0].get("posting_date"), se.doc.posting_date)
+		self.assertEqual(jv_list[1].get("account"), "_Test Customer - _TC")
+		self.assertEqual(jv_list[2].get("account"), "Sales - _TC")
+		self.assertTrue(jv_list[1].get("against_invoice"))
+		
+		# debit == credit
+		debit = sum([flt(d.get("debit")) for d in jv_list])
+		credit = sum([flt(d.get("credit")) for d in jv_list])
+		self.assertEqual(debit, credit)
+		
+		# validate value of debit
+		self.assertEqual(debit, returned_value)
+		
+	def test_make_return_jv_for_sales_invoice_non_packing_item(self):
+		se = self._test_sales_invoice_return("_Test Item", 5, 2)
+		self._test_sales_return_jv(se, 1000)
+		
+	def test_make_return_jv_for_sales_invoice_packing_item(self):
+		se = self._test_sales_invoice_return("_Test Sales BOM Item", 25, 20)
+		self._test_sales_return_jv(se, 2000)
+		
+	def test_make_return_jv_for_delivery_note_non_packing_item(self):
+		se = self._test_delivery_note_return("_Test Item", 5, 2)
+		self._test_sales_return_jv(se, 200)
+		
+		se = self._test_delivery_note_return_against_sales_order("_Test Item", 5, 2)
+		self._test_sales_return_jv(se, 200)
+		
+	def test_make_return_jv_for_delivery_note_packing_item(self):
+		se = self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
+		self._test_sales_return_jv(se, 400)
+		
+		se = self._test_delivery_note_return_against_sales_order("_Test Sales BOM Item", 25, 20)
+		self._test_sales_return_jv(se, 400)
+		
+	def _test_delivery_note_return_against_sales_order(self, item_code, delivered_qty, returned_qty):
+		self._insert_material_receipt()
+
+		from selling.doctype.sales_order.test_sales_order \
+			import test_records as sales_order_test_records
+
+		actual_qty_0 = self._get_actual_qty()
+		
+		so = webnotes.bean(copy=sales_order_test_records[0])
+		so.doclist[1].item_code = item_code
+		so.doclist[1].qty = 5.0
+		so.insert()
+		so.submit()
+		
+		dn_doclist = webnotes.map_doclist([
+			["Sales Order", "Delivery Note"],
+			["Sales Order Item", "Delivery Note Item"],
+			["Sales Taxes and Charges", "Sales Taxes and Charges"],
+			["Sales Team", "Sales Team"]], so.doc.name)
+
+		dn = webnotes.bean(dn_doclist)
+		dn.doc.status = "Draft"
+		dn.doc.posting_date = so.doc.delivery_date
+		dn.insert()
+		dn.submit()
+		
+		actual_qty_1 = self._get_actual_qty()
+
+		self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
+
+		si_doclist = webnotes.map_doclist([
+			["Sales Order", "Sales Invoice"],
+			["Sales Order Item", "Sales Invoice Item"],
+			["Sales Taxes and Charges", "Sales Taxes and Charges"],
+			["Sales Team", "Sales Team"]], so.doc.name)
+
+		si = webnotes.bean(si_doclist)
+		si.doc.posting_date = dn.doc.posting_date
+		si.doc.debit_to = "_Test Customer - _TC"
+		for d in si.doclist.get({"parentfield": "entries"}):
+			d.income_account = "Sales - _TC"
+			d.cost_center = "_Test Cost Center - _TC"
+		si.insert()
+		si.submit()
+
+		# insert and submit stock entry for sales return
+		se = webnotes.bean(copy=test_records[0])
+		se.doc.purpose = "Sales Return"
+		se.doc.delivery_note_no = dn.doc.name
+		se.doc.posting_date = "2013-03-10"
+		se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
+
+		se.insert()
+		se.submit()
+
+		actual_qty_2 = self._get_actual_qty()
+		self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
+
+		return se
+		
 	def test_purchase_receipt_return(self):
 		self._clear_stock()
 		
@@ -298,6 +427,24 @@
 		
 		self.assertEquals(actual_qty_0 + 10, actual_qty_1)
 		
+		pi_doclist = webnotes.map_doclist([
+			["Purchase Receipt", "Purchase Invoice"],
+			["Purchase Receipt Item", "Purchase Invoice Item"],
+			["Purchase Taxes and Charges", "Purchase Taxes and Charges"]], pr.doc.name)
+			
+		pi = webnotes.bean(pi_doclist)
+		pi.doc.posting_date = pr.doc.posting_date
+		pi.doc.credit_to = "_Test Supplier - _TC"
+		for d in pi.doclist.get({"parentfield": "entries"}):
+			d.expense_head = "_Test Account Cost for Goods Sold - _TC"
+			d.cost_center = "_Test Cost Center - _TC"
+		for d in pi.doclist.get({"parentfield": "purchase_tax_details"}):
+			d.cost_center = "_Test Cost Center - _TC"
+		
+		pi.run_method("calculate_taxes_and_totals")
+		pi.insert()
+		pi.submit()
+		
 		# submit purchase return
 		se = webnotes.bean(copy=test_records[0])
 		se.doc.purpose = "Purchase Return"
@@ -312,13 +459,13 @@
 		
 		self.assertEquals(actual_qty_1 - 5, actual_qty_2)
 		
-		return pr.doc.name
+		return se, pr.doc.name
 		
 	def test_over_stock_return(self):
 		from stock.doctype.stock_entry.stock_entry import StockOverReturnError
 		
 		# out of 10, 5 gets returned
-		pr_docname = self.test_purchase_receipt_return()
+		prev_se, pr_docname = self.test_purchase_receipt_return()
 		
 		# submit purchase return - return another 6 qtys so that exception is raised
 		se = webnotes.bean(copy=test_records[0])
@@ -329,7 +476,97 @@
 		se.doclist[1].s_warehouse = "_Test Warehouse"
 		
 		self.assertRaises(StockOverReturnError, se.insert)
-
+		
+	def _test_purchase_return_jv(self, se, returned_value):
+		from stock.doctype.stock_entry.stock_entry import make_return_jv
+		jv_list = make_return_jv(se.doc.name)
+		
+		self.assertEqual(len(jv_list), 3)
+		self.assertEqual(jv_list[0].get("voucher_type"), "Debit Note")
+		self.assertEqual(jv_list[0].get("posting_date"), se.doc.posting_date)
+		self.assertEqual(jv_list[1].get("account"), "_Test Supplier - _TC")
+		self.assertEqual(jv_list[2].get("account"), "_Test Account Cost for Goods Sold - _TC")
+		self.assertTrue(jv_list[1].get("against_voucher"))
+		
+		# debit == credit
+		debit = sum([flt(d.get("debit")) for d in jv_list])
+		credit = sum([flt(d.get("credit")) for d in jv_list])
+		self.assertEqual(debit, credit)
+		
+		# validate value of credit
+		self.assertEqual(credit, returned_value)
+		
+	def test_make_return_jv_for_purchase_receipt(self):
+		se, pr_name = self.test_purchase_receipt_return()
+		self._test_purchase_return_jv(se, 250)
+		
+		se, pr_name = self._test_purchase_return_return_against_purchase_order()
+		self._test_purchase_return_jv(se, 250)
+		
+	def _test_purchase_return_return_against_purchase_order(self):
+		self._clear_stock()
+		
+		actual_qty_0 = self._get_actual_qty()
+		
+		from buying.doctype.purchase_order.test_purchase_order \
+			import test_records as purchase_order_test_records
+		
+		# submit purchase receipt
+		po = webnotes.bean(copy=purchase_order_test_records[0])
+		po.doc.is_subcontracted = None
+		po.doclist[1].item_code = "_Test Item"
+		po.doclist[1].import_rate = 50
+		po.insert()
+		po.submit()
+		
+		pr_doclist = webnotes.map_doclist([
+			["Purchase Order", "Purchase Receipt"],
+			["Purchase Order Item", "Purchase Receipt Item"],
+			["Purchase Taxes and Charges", "Purchase Taxes and Charges"]], po.doc.name)
+		
+		pr = webnotes.bean(pr_doclist)
+		pr.doc.posting_date = po.doc.transaction_date
+		pr.insert()
+		pr.submit()
+		
+		actual_qty_1 = self._get_actual_qty()
+		
+		self.assertEquals(actual_qty_0 + 10, actual_qty_1)
+		
+		pi_doclist = webnotes.map_doclist([
+			["Purchase Order", "Purchase Invoice"],
+			["Purchase Order Item", "Purchase Invoice Item"],
+			["Purchase Taxes and Charges", "Purchase Taxes and Charges"]], po.doc.name)
+			
+		pi = webnotes.bean(pi_doclist)
+		pi.doc.posting_date = pr.doc.posting_date
+		pi.doc.credit_to = "_Test Supplier - _TC"
+		for d in pi.doclist.get({"parentfield": "entries"}):
+			d.expense_head = "_Test Account Cost for Goods Sold - _TC"
+			d.cost_center = "_Test Cost Center - _TC"
+		for d in pi.doclist.get({"parentfield": "purchase_tax_details"}):
+			d.cost_center = "_Test Cost Center - _TC"
+		
+		pi.run_method("calculate_taxes_and_totals")
+		pi.insert()
+		pi.submit()
+		
+		# submit purchase return
+		se = webnotes.bean(copy=test_records[0])
+		se.doc.purpose = "Purchase Return"
+		se.doc.purchase_receipt_no = pr.doc.name
+		se.doc.posting_date = "2013-03-01"
+		se.doclist[1].qty = se.doclist[1].transfer_qty = 5
+		se.doclist[1].s_warehouse = "_Test Warehouse"
+		se.insert()
+		se.submit()
+		
+		actual_qty_2 = self._get_actual_qty()
+		
+		self.assertEquals(actual_qty_1 - 5, actual_qty_2)
+		
+		return se, pr.doc.name
+		
 test_records = [
 	[
 		{