validate over-return of stock for sales purchase return
diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js
index 010b270..1581844 100644
--- a/stock/doctype/stock_entry/stock_entry.js
+++ b/stock/doctype/stock_entry/stock_entry.js
@@ -66,6 +66,17 @@
 		if (this.frm.doc.docstatus==1) {
 			this.show_stock_ledger();
 		}
+		
+		if(this.frm.doc.docstatus === 1 && wn.boot.profile.can_create("Journal Voucher")) {
+			if(this.frm.doc.purpose === "Sales Return") {
+				this.frm.add_custom_button("Make Credit Note", this.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.add_excise_button();
+			}
+		}
+		
 	},
 	
 	on_submit: function() {
@@ -143,6 +154,29 @@
 			}
 		}
 	},
+	
+	add_excise_button: function() {
+		if(wn.boot.control_panel.country === "India")
+			this.frm.add_custom_button("Make Excise Invoice", function() {
+				var excise = wn.model.make_new_doc_and_get_name('Journal Voucher');
+				excise = locals['Journal Voucher'][excise];
+				excise.voucher_type = 'Excise Voucher';
+				loaddoc('Journal Voucher', excise.name);
+			});
+	},
+	
+	make_return_jv: function() {
+		this.frm.call({
+			method: "make_return_jv",
+			args: {
+				stock_entry: this.frm.doc.name
+			},
+			callback: function(r) {
+				console.log(r);
+				loaddoc("Journal Voucher", r.message);
+			}
+		});
+	},
 
 });
 
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index 38ab5ba..80756b4 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -29,6 +29,7 @@
 sql = webnotes.conn.sql
 
 class NotUpdateStockError(webnotes.ValidationError): pass
+class StockOverReturnError(webnotes.ValidationError): pass
 	
 from controllers.accounts_controller import AccountsController
 
@@ -278,32 +279,24 @@
 						
 	def validate_return_reference_doc(self):
 		"""validate item with reference doc"""
-		ref_doclist = parentfields = None
+		ref = get_return_reference_details(self.doc.fields)
 		
-		# get ref_doclist
-		if self.doc.purpose in return_map:
-			for fieldname, val in return_map[self.doc.purpose].items():
-				if self.doc.fields.get(fieldname):
-					ref_doclist = webnotes.get_doclist(val[0], self.doc.fields[fieldname])
-					parentfields = val[1]
-		
-		if ref_doclist:
+		if ref.doclist:
 			# validate docstatus
-			if ref_doclist[0].docstatus != 1:
-				webnotes.msgprint(_(ref_doclist[0].doctype) + ' "' + ref_doclist[0].name + '": ' 
+			if ref.doclist[0].docstatus != 1:
+				webnotes.msgprint(_(ref.doclist[0].doctype) + ' "' + ref.doclist[0].name + '": ' 
 					+ _("Status should be Submitted"), raise_exception=webnotes.InvalidStatusError)
 			
-			
 			# update stock check
-			if ref_doclist[0].doctype == "Sales Invoice" and (cint(ref_doclist[0].is_pos) != 1 \
-				or cint(ref_doclist[0].update_stock) != 1):
-					webnotes.msgprint(_(ref_doclist[0].doctype) + ' "' + ref_doclist[0].name + '": ' 
+			if ref.doclist[0].doctype == "Sales Invoice" and (cint(ref.doclist[0].is_pos) != 1 \
+				or cint(ref.doclist[0].update_stock) != 1):
+					webnotes.msgprint(_(ref.doclist[0].doctype) + ' "' + ref.doclist[0].name + '": ' 
 						+ _("Is POS and Update Stock should be checked."), 
 						raise_exception=NotUpdateStockError)
 			
 			# posting date check
-			ref_posting_datetime = "%s %s" % (cstr(ref_doclist[0].posting_date), 
-				cstr(ref_doclist[0].posting_time))
+			ref_posting_datetime = "%s %s" % (cstr(ref.doclist[0].posting_date), 
+				cstr(ref.doclist[0].posting_time))
 			this_posting_datetime = "%s %s" % (cstr(self.doc.posting_date), 
 				cstr(self.doc.posting_time))
 			if this_posting_datetime < ref_posting_datetime:
@@ -312,18 +305,27 @@
 					+ ": " + datetime_in_user_format(ref_posting_datetime),
 					raise_exception=True)
 			
-			stock_items = get_stock_items_for_return(ref_doclist, parentfields)
+			stock_items = get_stock_items_for_return(ref.doclist, ref.parentfields)
+			already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname)
 			
 			for item in self.doclist.get({"parentfield": "mtn_details"}):
 				# validate if item exists in the ref doclist and that it is a stock item
 				if item.item_code not in stock_items:
 					msgprint(_("Item") + ': "' + item.item_code + _("\" does not exist in ") +
-						ref_doclist[0].doctype + ": " + ref_doclist[0].name, 
+						ref.doclist[0].doctype + ": " + ref.doclist[0].name, 
 						raise_exception=webnotes.DoesNotExistError)
 				
-				# validate quantity <= ref item's qty
-				ref_item = ref_doclist.getone({"item_code": item.item_code})
-				self.validate_value("transfer_qty", "<=", ref_item.qty, item)
+				# validate quantity <= ref item's qty - qty already returned
+				ref_item = ref.doclist.getone({"item_code": item.item_code})
+				returnable_qty = ref_item.qty - flt(already_returned_item_qty.get(item.item_code))
+				self.validate_value("transfer_qty", "<=", returnable_qty, item,
+					raise_exception=StockOverReturnError)
+				
+	def get_already_returned_item_qty(self, ref_fieldname):
+		return dict(webnotes.conn.sql("""select item_code, sum(transfer_qty) as qty
+			from `tabStock Entry Detail` where parent in (
+				select name from `tabStock Entry` where `%s`=%s and docstatus=1)
+			group by item_code""" % (ref_fieldname, "%s"), (self.doc.fields.get(ref_fieldname),)))
 		
 	def update_serial_no(self, is_submit):
 		"""Create / Update Serial No"""
@@ -670,7 +672,7 @@
 						+ " " + _("Row #") + (" %d %s " % (mreq_item.idx, _("of")))
 						+ _("Material Request") + (" - %s" % item.material_request), 
 						raise_exception=webnotes.MappingMismatchError)
-
+	
 @webnotes.whitelist()
 def get_production_order_details(production_order):
 	result = webnotes.conn.sql("""select bom_no, 
@@ -700,16 +702,13 @@
 		
 def query_return_item(doctype, txt, searchfield, start, page_len, filters):
 	txt = txt.replace("%", "")
-	
-	for fieldname, val in return_map[filters["purpose"]].items():
-		if filters.get(fieldname):
-			ref_doclist = webnotes.get_doclist(val[0], filters[fieldname])
-			parentfields = val[1]
+
+	ref = get_return_reference_details(filters)
 			
-	stock_items = get_stock_items_for_return(ref_doclist, parentfields)
+	stock_items = get_stock_items_for_return(ref.doclist, ref.parentfields)
 	
 	result = []
-	for item in ref_doclist.get({"parentfield": ["in", parentfields]}):
+	for item in ref.doclist.get({"parentfield": ["in", ref.parentfields]}):
 		if item.item_code in stock_items:
 			item.item_name = cstr(item.item_name)
 			item.description = cstr(item.description)
@@ -738,6 +737,20 @@
 
 	return stock_items
 	
+def get_return_reference_details(args):
+	ref = webnotes._dict()
+	
+	# get ref_doclist
+	if args["purpose"] in return_map:
+		for fieldname, val in return_map[args["purpose"]].items():
+			if args.get(fieldname):
+				ref.fieldname = fieldname
+				ref.doclist = webnotes.get_doclist(val[0], args[fieldname])
+				ref.parentfields = val[1]
+				break
+				
+	return ref
+	
 return_map = {
 	"Sales Return": {
 		# [Ref DocType, [Item tables' parentfields]]
@@ -748,3 +761,18 @@
 		"purchase_receipt_no": ["Purchase Receipt", ["purchase_receipt_details"]]
 	}
 }
+
+def make_return_jv(stock_entry):
+	jv = webnotes.bean({
+		"doctype": "Journal Voucher",
+		"__islocal": 1
+	})
+	
+	se = webnotes.bean("Stock Entry", stock_entry)
+	
+	if not webnotes.response.get("docs"):
+		webnotes.response["docs"] = []
+	
+	webnotes.response["docs"] = jv.doclist
+	
+	return jv.doc.name
\ 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 caf3291..c0f8f28 100644
--- a/stock/doctype/stock_entry/test_stock_entry.py
+++ b/stock/doctype/stock_entry/test_stock_entry.py
@@ -312,6 +312,23 @@
 		
 		self.assertEquals(actual_qty_1 - 5, actual_qty_2)
 		
+		return 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()
+		
+		# submit purchase return - return another 6 qtys so that exception is raised
+		se = webnotes.bean(copy=test_records[0])
+		se.doc.purpose = "Purchase Return"
+		se.doc.purchase_receipt_no = pr_docname
+		se.doc.posting_date = "2013-03-01"
+		se.doclist[1].qty = se.doclist[1].transfer_qty = 6
+		se.doclist[1].s_warehouse = "_Test Warehouse"
+		
+		self.assertRaises(StockOverReturnError, se.insert)
 
 test_records = [
 	[