[refactor] added dynamic link in journal entry, #3847
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
index 7dd021e..f1c8820 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
@@ -19,7 +19,8 @@
 
 
 		dl = frappe.db.sql("""select t1.name, t1.cheque_no, t1.cheque_date, t2.debit,
-				t2.credit, t1.posting_date, t2.against_account, t1.clearance_date
+				t2.credit, t1.posting_date, t2.against_account, t1.clearance_date,
+				t2.reference_type, t2.reference_name
 			from
 				`tabJournal Entry` t1, `tabJournal Entry Account` t2
 			where
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json b/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
index b2c6e66..78691a3 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
+++ b/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
@@ -1,11 +1,19 @@
 {
+ "allow_copy": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
  "creation": "2013-02-22 01:27:37", 
+ "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
  "fields": [
   {
+   "allow_on_submit": 0, 
    "fieldname": "voucher_id", 
    "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 0, 
    "label": "Voucher ID", 
    "no_copy": 0, 
@@ -13,46 +21,84 @@
    "oldfieldtype": "Link", 
    "options": "Journal Entry", 
    "permlevel": 0, 
-   "search_index": 0
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "clearance_date", 
    "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Clearance Date", 
    "no_copy": 0, 
    "oldfieldname": "clearance_date", 
    "oldfieldtype": "Date", 
    "permlevel": 0, 
-   "search_index": 0
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "against_account", 
    "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Against Account", 
    "no_copy": 0, 
    "oldfieldname": "against_account", 
    "oldfieldtype": "Data", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "read_only": 1, 
-   "search_index": 0
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "cheque_number", 
    "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Cheque Number", 
    "no_copy": 0, 
    "oldfieldname": "cheque_number", 
    "oldfieldtype": "Data", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "read_only": 1, 
-   "search_index": 0
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "debit", 
    "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Debit", 
    "no_copy": 0, 
@@ -60,12 +106,21 @@
    "oldfieldtype": "Currency", 
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "read_only": 1, 
-   "search_index": 0
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "credit", 
    "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Credit", 
    "no_copy": 0, 
@@ -73,40 +128,113 @@
    "oldfieldtype": "Currency", 
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "read_only": 1, 
-   "search_index": 0
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
+   "fieldname": "reference_type", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Reference Type", 
+   "no_copy": 0, 
+   "options": "DocType", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "fieldname": "reference_name", 
+   "fieldtype": "Dynamic Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Reference Name", 
+   "no_copy": 0, 
+   "options": "reference_type", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
    "fieldname": "posting_date", 
    "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 0, 
    "label": "Posting Date", 
    "no_copy": 0, 
    "oldfieldname": "posting_date", 
    "oldfieldtype": "Date", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "read_only": 1, 
-   "search_index": 0
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "cheque_date", 
    "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Cheque Date", 
    "no_copy": 0, 
    "oldfieldname": "cheque_date", 
    "oldfieldtype": "Date", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "read_only": 1, 
-   "search_index": 0
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }
  ], 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
  "idx": 1, 
+ "in_create": 0, 
+ "in_dialog": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
  "istable": 1, 
- "modified": "2015-04-21 01:29:29.570890", 
+ "modified": "2015-08-10 16:59:43.974705", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Bank Reconciliation Detail", 
  "owner": "Administrator", 
- "permissions": []
+ "permissions": [], 
+ "read_only": 0, 
+ "read_only_onload": 0
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index ec17e34..38f3e0c 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -50,32 +50,43 @@
 
 		$.each([["against_voucher", "Purchase Invoice", "supplier"],
 			["against_invoice", "Sales Invoice", "customer"]], function(i, opts) {
-				me.frm.set_query(opts[0], "accounts", function(doc, cdt, cdn) {
-					var jvd = frappe.get_doc(cdt, cdn);
-					frappe.model.validate_missing(jvd, "party_type");
-					frappe.model.validate_missing(jvd, "party");
-					return {
-						filters: [
-							[opts[1], opts[2], "=", jvd.party],
-							[opts[1], "docstatus", "=", 1],
-							[opts[1], "outstanding_amount", "!=", 0]
-						]
-					};
-				});
 		});
 
-		this.frm.set_query("against_jv", "accounts", function(doc, cdt, cdn) {
+		me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
 			var jvd = frappe.get_doc(cdt, cdn);
-			frappe.model.validate_missing(jvd, "account");
 
+			// expense claim
+			if(jvd.reference_type==="Expense Claim") {
+				return {};
+			}
+
+			// journal entry
+			if(jvd.reference_type==="Journal Entry") {
+				frappe.model.validate_missing(jvd, "account");
+
+				return {
+					query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
+					filters: {
+						account: jvd.account,
+						party: jvd.party
+					}
+				};
+			}
+
+			// against party
+
+			frappe.model.validate_missing(jvd, "party_type");
+			frappe.model.validate_missing(jvd, "party");
 			return {
-				query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
-				filters: {
-					account: jvd.account,
-					party: jvd.party
-				}
+				filters: [
+					[jvd.reference_type, jvd.reference_type.indexOf("Sales")==1 ? "customer" : "supplier", "=", jvd.party],
+					[jvd.reference_type, "docstatus", "=", 1],
+					[jvd.reference_type, "outstanding_amount", "!=", 0]
+				]
 			};
 		});
+
+
 	},
 
 	setup_balance_formatter: function() {
@@ -93,24 +104,16 @@
 		})
 	},
 
-	against_voucher: function(doc, cdt, cdn) {
+	reference_name: function(doc, cdt, cdn) {
 		var d = frappe.get_doc(cdt, cdn);
-		if (d.against_voucher && !flt(d.debit)) {
-			this.get_outstanding('Purchase Invoice', d.against_voucher, d);
+		if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
+			this.get_outstanding('Purchase Invoice', d.reference_name, d);
 		}
-	},
-
-	against_invoice: function(doc, cdt, cdn) {
-		var d = frappe.get_doc(cdt, cdn);
-		if (d.against_invoice && !flt(d.credit)) {
-			this.get_outstanding('Sales Invoice', d.against_invoice, d);
+		if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
+			this.get_outstanding('Sales Invoice', d.reference_name, d);
 		}
-	},
-
-	against_jv: function(doc, cdt, cdn) {
-		var d = frappe.get_doc(cdt, cdn);
-		if (d.against_jv && !flt(d.credit) && !flt(d.debit)) {
-			this.get_outstanding('Journal Entry', d.against_jv, d);
+		if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
+			this.get_outstanding('Journal Entry', d.reference_name, d);
 		}
 	},
 
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 80d2435..b48e46c 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -28,13 +28,10 @@
 		self.validate_entries_for_advance()
 		self.validate_debit_and_credit()
 		self.validate_against_jv()
-		self.validate_against_sales_invoice()
-		self.validate_against_purchase_invoice()
+		self.validate_reference_doc()
 		self.set_against_account()
 		self.create_remarks()
 		self.set_print_format_fields()
-		self.validate_against_sales_order()
-		self.validate_against_purchase_order()
 		self.check_due_date()
 		self.validate_expense_claim()
 		self.validate_credit_debit_note()
@@ -54,10 +51,8 @@
 		advance_paid = frappe._dict()
 		for d in self.get("accounts"):
 			if d.is_advance:
-				if d.against_sales_order:
-					advance_paid.setdefault("Sales Order", []).append(d.against_sales_order)
-				elif d.against_purchase_order:
-					advance_paid.setdefault("Purchase Order", []).append(d.against_purchase_order)
+				if d.reference_type in ("Sales Order", "Purchase Order"):
+					advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
 
 		for voucher_type, order_list in advance_paid.items():
 			for voucher_no in list(set(order_list)):
@@ -65,7 +60,7 @@
 
 	def on_cancel(self):
 		from erpnext.accounts.utils import remove_against_link_from_jv
-		remove_against_link_from_jv(self.doctype, self.name, "against_jv")
+		remove_against_link_from_jv(self.doctype, self.name)
 
 		self.make_gl_entries(1)
 		self.update_advance_paid()
@@ -93,10 +88,8 @@
 			for d in self.get("accounts"):
 				if d.party_type and d.party and d.get("credit" if d.party_type=="Customer" else "debit") > 0:
 					due_date = None
-					if d.against_invoice:
-						due_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "due_date")
-					elif d.against_voucher:
-						due_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "due_date")
+					if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
+						due_date = frappe.db.get_value(d.reference_type, d.reference_name, "due_date")
 
 					if due_date and getdate(self.cheque_date) > getdate(due_date):
 						diff = date_diff(self.cheque_date, due_date)
@@ -115,17 +108,17 @@
 
 	def validate_entries_for_advance(self):
 		for d in self.get('accounts'):
-			if not (d.against_voucher and d.against_invoice and d.against_jv):
+			if d.reference_type not in ("Sales Invoice", "Purchase Invoice", "Journal Entry"):
 				if (d.party_type == 'Customer' and flt(d.credit) > 0) or \
 						(d.party_type == 'Supplier' and flt(d.debit) > 0):
-					if not d.is_advance:
+					if d.is_advance=="No":
 						msgprint(_("Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry.").format(d.idx, d.account))
-					elif (d.against_sales_order or d.against_purchase_order) and d.is_advance != "Yes":
+					elif d.reference_type in ("Sales Order", "Purchase Order") and d.is_advance != "Yes":
 						frappe.throw(_("Row {0}: Payment against Sales/Purchase Order should always be marked as advance").format(d.idx))
 
 	def validate_against_jv(self):
 		for d in self.get('accounts'):
-			if d.against_jv:
+			if d.reference_type=="Journal Voucher":
 				account_root_type = frappe.db.get_value("Account", d.account, "root_type")
 				if account_root_type == "Asset" and flt(d.debit) > 0:
 					frappe.throw(_("For {0}, only credit accounts can be linked against another debit entry")
@@ -134,17 +127,17 @@
 					frappe.throw(_("For {0}, only debit accounts can be linked against another credit entry")
 						.format(d.account))
 
-				if d.against_jv == self.name:
+				if d.reference_name == self.name:
 					frappe.throw(_("You can not enter current voucher in 'Against Journal Entry' column"))
 
 				against_entries = frappe.db.sql("""select * from `tabJournal Entry Account`
 					where account = %s and docstatus = 1 and parent = %s
-					and ifnull(against_jv, '') = '' and ifnull(against_invoice, '') = ''
-					and ifnull(against_voucher, '') = ''""", (d.account, d.against_jv), as_dict=True)
+					and ifnull(reference_type, '') = '' and ifnull(reference_name, '') = ''
+					""", (d.account, d.reference_name), as_dict=True)
 
 				if not against_entries:
 					frappe.throw(_("Journal Entry {0} does not have account {1} or already matched against other voucher")
-						.format(d.against_jv, d.account))
+						.format(d.reference_name, d.account))
 				else:
 					dr_or_cr = "debit" if d.credit > 0 else "credit"
 					valid = False
@@ -153,89 +146,99 @@
 							valid = True
 					if not valid:
 						frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
-							.format(d.against_jv, dr_or_cr))
+							.format(d.reference_name, dr_or_cr))
 
-	def validate_against_sales_invoice(self):
-		self.validate_account_in_against_voucher("against_invoice", "Sales Invoice")
-
-	def validate_against_purchase_invoice(self):
-		self.validate_account_in_against_voucher("against_voucher", "Purchase Invoice")
-
-	def validate_against_sales_order(self):
-		payment_against_voucher = self.validate_account_in_against_voucher("against_sales_order", "Sales Order")
-		self.validate_against_order_fields("Sales Order", payment_against_voucher)
-
-	def validate_against_purchase_order(self):
-		payment_against_voucher = self.validate_account_in_against_voucher("against_purchase_order", "Purchase Order")
-		self.validate_against_order_fields("Purchase Order", payment_against_voucher)
-
-	def validate_account_in_against_voucher(self, against_field, doctype):
-		payment_against_voucher = frappe._dict()
-		field_dict = {'Sales Invoice': ["Customer", "Debit To"],
+	def validate_reference_doc(self):
+		"""Validates reference document"""
+		field_dict = {
+			'Sales Invoice': ["Customer", "Debit To"],
 			'Purchase Invoice': ["Supplier", "Credit To"],
 			'Sales Order': ["Customer"],
 			'Purchase Order': ["Supplier"]
-			}
+		}
+
+		self.reference_totals = {}
+		self.reference_types = {}
 
 		for d in self.get("accounts"):
-			if d.get(against_field):
-				dr_or_cr = "credit" if against_field in ["against_invoice", "against_sales_order"] \
+			if not d.reference_type:
+				d.reference_name = None
+			if not d.reference_type:
+				d.reference_name = None
+			if d.reference_type and d.reference_name and (d.reference_type in field_dict.keys()):
+				dr_or_cr = "credit" if d.reference_type in ("Sales Order", "Sales Invoice") \
 					else "debit"
-				if against_field == "against_sales_order" and flt(d.debit) > 0:
-					frappe.throw(_("Row {0}: Debit entry can not be linked with a {1}").format(d.idx, doctype))
 
-				if against_field == "against_purchase_order" and flt(d.credit) > 0:
-					frappe.throw(_("Row {0}: Credit entry can not be linked with a {1}").format(d.idx, doctype))
+				# check debit or credit type Sales / Purchase Order
+				if d.reference_type=="Sales Order" and flt(d.debit) > 0:
+					frappe.throw(_("Row {0}: Debit entry can not be linked with a {1}").format(d.idx, d.reference_type))
 
-				against_voucher = frappe.db.get_value(doctype, d.get(against_field),
-					[scrub(dt) for dt in field_dict.get(doctype)])
+				if d.reference_type == "Purchase Order" and flt(d.credit) > 0:
+					frappe.throw(_("Row {0}: Credit entry can not be linked with a {1}").format(d.idx, d.reference_type))
 
-				if against_field in ["against_invoice", "against_voucher"]:
-					if (against_voucher[0] !=d.party or against_voucher[1] != d.account):
+				# set totals
+				if not d.reference_name in self.reference_totals:
+					self.reference_totals[d.reference_name] = 0.0
+				self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
+				self.reference_types[d.reference_name] = d.reference_type
+
+				against_voucher = frappe.db.get_value(d.reference_type, d.reference_name,
+					[scrub(dt) for dt in field_dict.get(d.reference_type)])
+
+				# check if party and account match
+				if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
+					if (against_voucher[0] != d.party or against_voucher[1] != d.account):
 						frappe.throw(_("Row {0}: Party / Account does not match with {1} / {2} in {3} {4}")
-							.format(d.idx, field_dict.get(doctype)[0], field_dict.get(doctype)[1], 
-								doctype, d.get(against_field)))
-					else:
-						payment_against_voucher.setdefault(d.get(against_field), []).append(flt(d.get(dr_or_cr)))
+							.format(d.idx, field_dict.get(d.reference_type)[0], field_dict.get(d.reference_type)[1],
+								d.reference_type, d.reference_name))
 
-				if against_field in ["against_sales_order", "against_purchase_order"]:
+				# check if party matches for Sales / Purchase Order
+				if d.reference_type in ("Sales Order", "Purchase Order"):
+					# set totals
 					if against_voucher != d.party:
 						frappe.throw(_("Row {0}: {1} {2} does not match with {3}") \
-							.format(d.idx, d.party_type, d.party, doctype))
-					elif d.is_advance == "Yes":
-						payment_against_voucher.setdefault(d.get(against_field), []).append(flt(d.get(dr_or_cr)))
+							.format(d.idx, d.party_type, d.party, d.reference_type))
 
-		return payment_against_voucher
+		self.validate_orders()
+		self.validate_invoices()
 
-	def validate_against_invoice_fields(self, doctype, payment_against_voucher):
-		for voucher_no, payment_list in payment_against_voucher.items():
-			voucher_properties = frappe.db.get_value(doctype, voucher_no, 
-				["docstatus", "outstanding_amount"])
+	def validate_orders(self):
+		"""Validate totals, stopped and docstatus for orders"""
+		for reference_name, total in self.reference_totals.iteritems():
+			reference_type = self.reference_types[reference_name]
 
-			if voucher_properties[0] != 1:
-				frappe.throw(_("{0} {1} is not submitted").format(doctype, voucher_no))
+			if reference_type in ("Sales Order", "Purchase Order"):
+				voucher_properties = frappe.db.get_value(reference_type, reference_name,
+					["docstatus", "per_billed", "status", "advance_paid", "base_grand_total"])
 
-			if flt(voucher_properties[1]) < flt(sum(payment_list)):
-				frappe.throw(_("Payment against {0} {1} cannot be greater \
-					than Outstanding Amount {2}").format(doctype, voucher_no, voucher_properties[1]))
+				if voucher_properties[0] != 1:
+					frappe.throw(_("{0} {1} is not submitted").format(reference_type, reference_name))
 
-	def validate_against_order_fields(self, doctype, payment_against_voucher):
-		for voucher_no, payment_list in payment_against_voucher.items():
-			voucher_properties = frappe.db.get_value(doctype, voucher_no,
-				["docstatus", "per_billed", "status", "advance_paid", "base_grand_total"])
+				if flt(voucher_properties[1]) >= 100:
+					frappe.throw(_("{0} {1} is fully billed").format(reference_type, reference_name))
 
-			if voucher_properties[0] != 1:
-				frappe.throw(_("{0} {1} is not submitted").format(doctype, voucher_no))
+				if cstr(voucher_properties[2]) == "Stopped":
+					frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
 
-			if flt(voucher_properties[1]) >= 100:
-				frappe.throw(_("{0} {1} is fully billed").format(doctype, voucher_no))
+				if flt(voucher_properties[4]) < (flt(voucher_properties[3]) + total):
+					frappe.throw(_("Advance paid against {0} {1} cannot be greater \
+						than Grand Total {2}").format(reference_type, reference_name, voucher_properties[4]))
 
-			if cstr(voucher_properties[2]) == "Stopped":
-				frappe.throw(_("{0} {1} is stopped").format(doctype, voucher_no))
+	def validate_invoices(self):
+		"""Validate totals and docstatus for invoices"""
+		for reference_name, total in self.reference_totals.iteritems():
+			reference_type = self.reference_types[reference_name]
 
-			if flt(voucher_properties[4]) < flt(voucher_properties[3]) + flt(sum(payment_list)):
-				frappe.throw(_("Advance paid against {0} {1} cannot be greater \
-					than Grand Total {2}").format(doctype, voucher_no, voucher_properties[3]))
+			if reference_type in ("Sales Invoice", "Purchase Invoice"):
+				voucher_properties = frappe.db.get_value(reference_type, reference_name,
+					["docstatus", "outstanding_amount"])
+
+				if voucher_properties[0] != 1:
+					frappe.throw(_("{0} {1} is not submitted").format(reference_type, reference_name))
+
+				if flt(voucher_properties[1]) < total:
+					frappe.throw(_("Payment against {0} {1} cannot be greater \
+						than Outstanding Amount {2}").format(reference_type, reference_name, voucher_properties[1]))
 
 	def set_against_account(self):
 		accounts_debited, accounts_credited = [], []
@@ -275,25 +278,25 @@
 		company_currency = get_company_currency(self.company)
 
 		for d in self.get('accounts'):
-			if d.against_invoice and d.credit:
+			if d.reference_type=="Sales Invoice" and d.credit:
 				r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
-					d.against_invoice))
+					d.reference_name))
 
-			if d.against_sales_order and d.credit:
+			if d.reference_type=="Sales Order" and d.credit:
 				r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
-					d.against_sales_order))
+					d.reference_name))
 
-			if d.against_voucher and d.debit:
+			if d.reference_type == "Purchase Invoice" and d.debit:
 				bill_no = frappe.db.sql("""select bill_no, bill_date
-					from `tabPurchase Invoice` where name=%s""", d.against_voucher)
+					from `tabPurchase Invoice` where name=%s""", d.reference_name)
 				if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
 						not in ['na', 'not applicable', 'none']:
 					r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=company_currency), bill_no[0][0],
 						bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
 
-			if d.against_purchase_order and d.debit:
+			if d.reference_type == "Purchase Order" and d.debit:
 				r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
-					d.against_purchase_order))
+					d.reference_name))
 
 		if self.user_remark:
 			r.append(_("Note: {0}").format(self.user_remark))
@@ -332,13 +335,8 @@
 						"against": d.against_account,
 						"debit": flt(d.debit, self.precision("debit", "accounts")),
 						"credit": flt(d.credit, self.precision("credit", "accounts")),
-						"against_voucher_type": (("Purchase Invoice" if d.against_voucher else None)
-							or ("Sales Invoice" if d.against_invoice else None)
-							or ("Journal Entry" if d.against_jv else None)
-							or ("Sales Order" if d.against_sales_order else None)
-							or ("Purchase Order" if d.against_purchase_order else None)),
-						"against_voucher": d.against_voucher or d.against_invoice or d.against_jv
-							or d.against_sales_order or d.against_purchase_order,
+						"against_voucher_type": d.reference_type,
+						"against_voucher": d.reference_name,
 						"remarks": self.remark,
 						"cost_center": d.cost_center
 					})
@@ -385,11 +383,13 @@
 			if self.write_off_based_on == 'Accounts Receivable':
 				jd1.party_type = "Customer"
 				jd1.credit = flt(d.outstanding_amount, self.precision("credit", "accounts"))
-				jd1.against_invoice = cstr(d.name)
+				jd1.reference_type = "Sales Invoice"
+				jd1.reference_name = cstr(d.name)
 			elif self.write_off_based_on == 'Accounts Payable':
 				jd1.party_type = "Supplier"
 				jd1.debit = flt(d.outstanding_amount, self.precision("debit", "accounts"))
-				jd1.against_voucher = cstr(d.name)
+				jd1.reference_type = "Purchase Invoice"
+				jd1.reference_name = cstr(d.name)
 
 		jd2 = self.append('accounts', {})
 		if self.write_off_based_on == 'Accounts Receivable':
@@ -415,19 +415,20 @@
 
 	def update_expense_claim(self):
 		for d in self.accounts:
-			if d.against_expense_claim:
+			if d.reference_type=="Expense Claim":
 				amt = frappe.db.sql("""select sum(debit) as amt from `tabJournal Entry Account`
-					where against_expense_claim = %s and docstatus = 1""", d.against_expense_claim ,as_dict=1)[0].amt
-				frappe.db.set_value("Expense Claim", d.against_expense_claim , "total_amount_reimbursed", amt)
+					where reference_type = "Expense Claim" and
+					reference_name = %s and docstatus = 1""", d.reference_name ,as_dict=1)[0].amt
+				frappe.db.set_value("Expense Claim", d.reference_name , "total_amount_reimbursed", amt)
 
 	def validate_expense_claim(self):
 		for d in self.accounts:
-			if d.against_expense_claim:
+			if d.reference_type=="Expense Claim":
 				sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim",
-					d.against_expense_claim, ("total_sanctioned_amount", "total_amount_reimbursed"))
+					d.reference_name, ("total_sanctioned_amount", "total_amount_reimbursed"))
 				pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
 				if d.debit > pending_amount:
-					frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
+					frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.reference_name, pending_amount)))
 
 	def validate_credit_debit_note(self):
 		if self.stock_entry:
@@ -467,6 +468,7 @@
 
 @frappe.whitelist()
 def get_payment_entry_from_sales_invoice(sales_invoice):
+	"""Returns new Journal Entry document as dict for given Sales Invoice"""
 	from erpnext.accounts.utils import get_balance_on
 	si = frappe.get_doc("Sales Invoice", sales_invoice)
 	jv = get_payment_entry(si)
@@ -479,7 +481,8 @@
 	jv.get("accounts")[0].balance = get_balance_on(si.debit_to)
 	jv.get("accounts")[0].party_balance = get_balance_on(party=si.customer, party_type="Customer")
 	jv.get("accounts")[0].credit = si.outstanding_amount
-	jv.get("accounts")[0].against_invoice = si.name
+	jv.get("accounts")[0].reference_type = si.doctype
+	jv.get("accounts")[0].reference_name = si.name
 
 	# debit bank
 	jv.get("accounts")[1].debit = si.outstanding_amount
@@ -488,6 +491,7 @@
 
 @frappe.whitelist()
 def get_payment_entry_from_purchase_invoice(purchase_invoice):
+	"""Returns new Journal Entry document as dict for given Purchase Invoice"""
 	pi = frappe.get_doc("Purchase Invoice", purchase_invoice)
 	jv = get_payment_entry(pi)
 	jv.remark = 'Payment against Purchase Invoice {0}. {1}'.format(pi.name, pi.remarks)
@@ -499,13 +503,78 @@
 	jv.get("accounts")[0].balance = get_balance_on(pi.credit_to)
 	jv.get("accounts")[0].party_balance = get_balance_on(party=pi.supplier, party_type="Supplier")
 	jv.get("accounts")[0].debit = pi.outstanding_amount
-	jv.get("accounts")[0].against_voucher = pi.name
+	jv.get("accounts")[0].reference_type = pi.doctype
+	jv.get("accounts")[0].reference_name = pi.name
 
 	# credit bank
 	jv.get("accounts")[1].credit = pi.outstanding_amount
 
 	return jv.as_dict()
 
+@frappe.whitelist()
+def get_payment_entry_from_sales_order(sales_order):
+	"""Returns new Journal Entry document as dict for given Sales Order"""
+	from erpnext.accounts.utils import get_balance_on
+	from erpnext.accounts.party import get_party_account
+	so = frappe.get_doc("Sales Order", sales_order)
+
+	if flt(so.per_billed, 2) != 0.0:
+		frappe.throw(_("Can only make payment against unbilled Sales Order"))
+
+	jv = get_payment_entry(so)
+	jv.remark = 'Advance payment received against Sales Order {0}.'.format(so.name)
+	party_account = get_party_account(so.company, so.customer, "Customer")
+
+	amount = flt(so.base_grand_total) - flt(so.advance_paid)
+
+	# credit customer
+	jv.get("accounts")[0].account = party_account
+	jv.get("accounts")[0].party_type = "Customer"
+	jv.get("accounts")[0].party = so.customer
+	jv.get("accounts")[0].balance = get_balance_on(party_account)
+	jv.get("accounts")[0].party_balance = get_balance_on(party=so.customer, party_type="Customer")
+	jv.get("accounts")[0].credit = amount
+	jv.get("accounts")[0].reference_type = so.doctype
+	jv.get("accounts")[0].reference_name = so.name
+	jv.get("accounts")[0].is_advance = "Yes"
+
+	# debit bank
+	jv.get("accounts")[1].debit = amount
+
+	return jv.as_dict()
+
+@frappe.whitelist()
+def get_payment_entry_from_purchase_order(purchase_order):
+	"""Returns new Journal Entry document as dict for given Sales Order"""
+	from erpnext.accounts.utils import get_balance_on
+	from erpnext.accounts.party import get_party_account
+	po = frappe.get_doc("Purchase Order", purchase_order)
+
+	if flt(po.per_billed, 2) != 0.0:
+		frappe.throw(_("Can only make payment against unbilled Sales Order"))
+
+	jv = get_payment_entry(po)
+	jv.remark = 'Advance payment made against Purchase Order {0}.'.format(po.name)
+	party_account = get_party_account(po.company, po.supplier, "Supplier")
+
+	amount = flt(po.base_grand_total) - flt(po.advance_paid)
+
+	# credit customer
+	jv.get("accounts")[0].account = party_account
+	jv.get("accounts")[0].party_type = "Supplier"
+	jv.get("accounts")[0].party = po.supplier
+	jv.get("accounts")[0].balance = get_balance_on(party_account)
+	jv.get("accounts")[0].party_balance = get_balance_on(party=po.supplier, party_type="Supplier")
+	jv.get("accounts")[0].debit = amount
+	jv.get("accounts")[0].reference_type = po.doctype
+	jv.get("accounts")[0].reference_name = po.name
+	jv.get("accounts")[0].is_advance = "Yes"
+
+	# debit bank
+	jv.get("accounts")[1].credit = amount
+
+	return jv.as_dict()
+
 def get_payment_entry(doc):
 	bank_account = get_default_bank_cash_account(doc.company, "Bank Entry")
 
@@ -536,8 +605,7 @@
 	return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
 		from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
 		where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
-		and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
-		and ifnull(jv_detail.against_jv, '') = '' )
+		and (ifnull(jv_detail.reference_type, '') = ''
 		and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
 		(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
 
@@ -546,12 +614,11 @@
 	args = eval(args)
 	if args.get("doctype") == "Journal Entry":
 		condition = " and party=%(party)s" if args.get("party") else ""
-			
+
 		against_jv_amount = frappe.db.sql("""
 			select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
 			from `tabJournal Entry Account` where parent=%(docname)s and account=%(account)s {0}
-			and ifnull(against_invoice, '')='' and ifnull(against_voucher, '')=''
-			and ifnull(against_jv, '')=''""".format(condition), args)
+			and ifnull(reference_type, '')=''""".format(condition), args)
 
 		against_jv_amount = flt(against_jv_amount[0][0]) if against_jv_amount else 0
 		return {
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
index 2aa60f0..c70f10d 100644
--- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
@@ -29,10 +29,6 @@
 
 	def jv_against_voucher_testcase(self, base_jv, test_voucher):
 		dr_or_cr = "credit" if test_voucher.doctype in ["Sales Order", "Journal Entry"] else "debit"
-		field_dict = {'Journal Entry': "against_jv",
-			'Sales Order': "against_sales_order",
-			'Purchase Order': "against_purchase_order"
-			}
 
 		test_voucher.insert()
 		test_voucher.submit()
@@ -42,21 +38,20 @@
 				where account = %s and docstatus = 1 and parent = %s""",
 				("_Test Receivable - _TC", test_voucher.name)))
 
-		self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
-			where %s=%s""" % (field_dict.get(test_voucher.doctype), '%s'), (test_voucher.name)))
+		self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
+			where reference_type = %s and reference_name = %s""", (test_voucher.doctype, test_voucher.name)))
 
 		base_jv.get("accounts")[0].is_advance = "Yes" if (test_voucher.doctype in ["Sales Order", "Purchase Order"]) else "No"
-		base_jv.get("accounts")[0].set(field_dict.get(test_voucher.doctype), test_voucher.name)
+		base_jv.get("accounts")[0].set("reference_type", test_voucher.doctype)
+		base_jv.get("accounts")[0].set("reference_name", test_voucher.name)
 		base_jv.insert()
 		base_jv.submit()
 
 		submitted_voucher = frappe.get_doc(test_voucher.doctype, test_voucher.name)
 
 		self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
-			where %s=%s""" % (field_dict.get(test_voucher.doctype), '%s'), (submitted_voucher.name)))
-
-		self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
-			where %s=%s and %s=400""" % (field_dict.get(submitted_voucher.doctype), '%s', dr_or_cr), (submitted_voucher.name)))
+			where reference_type = %s and reference_name = %s and {0}=400""".format(dr_or_cr),
+				(submitted_voucher.doctype, submitted_voucher.name)))
 
 		if base_jv.get("accounts")[0].is_advance == "Yes":
 			self.advance_paid_testcase(base_jv, submitted_voucher, dr_or_cr)
@@ -102,23 +97,23 @@
 
 	def test_monthly_budget_crossed_ignore(self):
 		frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
-		
+
 		self.set_total_expense_zero("2013-02-28")
-		
-		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", 
+
+		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
 			"_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC", submit=True)
-			
+
 		self.assertTrue(frappe.db.get_value("GL Entry",
 			{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
 
 	def test_monthly_budget_crossed_stop(self):
 		frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop")
-		
+
 		self.set_total_expense_zero("2013-02-28")
-		
-		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", 
+
+		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
 			"_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC")
-		
+
 		self.assertRaises(BudgetError, jv.submit)
 
 		frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
@@ -127,37 +122,37 @@
 		self.test_monthly_budget_crossed_ignore()
 
 		frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Stop")
-		
+
 		self.set_total_expense_zero("2013-02-28")
 
-		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", 
+		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
 			"_Test Account Bank Account - _TC", 150000, "_Test Cost Center - _TC")
-		
+
 		self.assertRaises(BudgetError, jv.submit)
 
 		frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Ignore")
 
 	def test_monthly_budget_on_cancellation(self):
 		self.set_total_expense_zero("2013-02-28")
-		
-		jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC", 
+
+		jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
 			"_Test Account Bank Account - _TC", 20000, "_Test Cost Center - _TC", submit=True)
-		
+
 		self.assertTrue(frappe.db.get_value("GL Entry",
 			{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
-			
-		jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC", 
+
+		jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
 			"_Test Account Bank Account - _TC", 20000, "_Test Cost Center - _TC", submit=True)
-		
+
 		self.assertTrue(frappe.db.get_value("GL Entry",
 			{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
-			
+
 		frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop")
 
 		self.assertRaises(BudgetError, jv1.cancel)
 
 		frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
-		
+
 	def get_actual_expense(self, monthly_end_date):
 		return get_actual_expense({
 			"account": "_Test Account Cost for Goods Sold - _TC",
@@ -166,19 +161,19 @@
 			"company": "_Test Company",
 			"fiscal_year": get_fiscal_year(monthly_end_date)[0]
 		})
-		
+
 	def set_total_expense_zero(self, posting_date):
 		existing_expense = self.get_actual_expense(posting_date)
-		make_journal_entry("_Test Account Cost for Goods Sold - _TC", 
+		make_journal_entry("_Test Account Cost for Goods Sold - _TC",
 			"_Test Account Bank Account - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
-		
+
 def make_journal_entry(account1, account2, amount, cost_center=None, submit=False):
 	jv = frappe.new_doc("Journal Entry")
 	jv.posting_date = "2013-02-14"
 	jv.company = "_Test Company"
 	jv.fiscal_year = "_Test Fiscal Year 2013"
 	jv.user_remark = "test"
-	
+
 	jv.set("accounts", [
 		{
 			"account": account1,
@@ -193,11 +188,11 @@
 		}
 	])
 	jv.insert()
-	
+
 	if submit:
 		jv.submit()
-	
+
 	return jv
-		
+
 
 test_records = frappe.get_test_records('Journal Entry')
diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
index b336d49..d091714 100644
--- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
+++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
@@ -1,27 +1,44 @@
 {
+ "allow_copy": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
  "autoname": "hash", 
  "creation": "2013-02-22 01:27:39", 
+ "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
  "fields": [
   {
+   "allow_on_submit": 0, 
    "fieldname": "account", 
    "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
    "in_filter": 1, 
    "in_list_view": 1, 
    "label": "Account", 
+   "no_copy": 0, 
    "oldfieldname": "account", 
    "oldfieldtype": "Link", 
    "options": "Account", 
    "permlevel": 0, 
+   "print_hide": 0, 
    "print_width": "250px", 
+   "read_only": 0, 
+   "report_hide": 0, 
    "reqd": 1, 
    "search_index": 1, 
+   "set_only_once": 0, 
+   "unique": 0, 
    "width": "250px"
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "balance", 
    "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Account Balance", 
    "no_copy": 1, 
@@ -30,186 +47,336 @@
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "print_hide": 1, 
-   "read_only": 1
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "default": ":Company", 
    "description": "If Income or Expense", 
    "fieldname": "cost_center", 
    "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
    "in_filter": 1, 
    "in_list_view": 1, 
    "label": "Cost Center", 
+   "no_copy": 0, 
    "oldfieldname": "cost_center", 
    "oldfieldtype": "Link", 
    "options": "Cost Center", 
    "permlevel": 0, 
    "print_hide": 1, 
    "print_width": "180px", 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
    "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0, 
    "width": "180px"
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "col_break1", 
    "fieldtype": "Column Break", 
-   "permlevel": 0
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "party_type", 
    "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Party Type", 
+   "no_copy": 0, 
    "options": "DocType", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "party", 
    "fieldtype": "Dynamic Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Party", 
+   "no_copy": 0, 
    "options": "party_type", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "party_balance", 
    "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Party Balance", 
+   "no_copy": 0, 
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
-   "read_only": 1
+   "print_hide": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "sec_break1", 
    "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Amount", 
-   "permlevel": 0
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "debit", 
    "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Debit", 
+   "no_copy": 0, 
    "oldfieldname": "debit", 
    "oldfieldtype": "Currency", 
    "options": "Company:company:default_currency", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "col_break2", 
    "fieldtype": "Column Break", 
-   "permlevel": 0
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "credit", 
    "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Credit", 
+   "no_copy": 0, 
    "oldfieldname": "credit", 
    "oldfieldtype": "Currency", 
    "options": "Company:company:default_currency", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "reference", 
    "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Reference", 
-   "permlevel": 0
-  }, 
-  {
-   "fieldname": "against_invoice", 
-   "fieldtype": "Link", 
-   "in_filter": 1, 
-   "label": "Against Sales Invoice", 
-   "no_copy": 1, 
-   "oldfieldname": "against_invoice", 
-   "oldfieldtype": "Link", 
-   "options": "Sales Invoice", 
+   "no_copy": 0, 
    "permlevel": 0, 
    "print_hide": 0, 
-   "search_index": 1
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
-   "fieldname": "against_voucher", 
-   "fieldtype": "Link", 
-   "in_filter": 1, 
-   "in_list_view": 1, 
-   "label": "Against Purchase Invoice", 
-   "no_copy": 1, 
-   "oldfieldname": "against_voucher", 
-   "oldfieldtype": "Link", 
-   "options": "Purchase Invoice", 
+   "allow_on_submit": 0, 
+   "fieldname": "reference_type", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Reference Type", 
+   "no_copy": 0, 
+   "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim", 
    "permlevel": 0, 
+   "precision": "", 
    "print_hide": 0, 
-   "search_index": 1
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
-   "fieldname": "against_jv", 
-   "fieldtype": "Link", 
-   "in_filter": 1, 
-   "label": "Against Journal Entry", 
-   "no_copy": 1, 
-   "oldfieldname": "against_jv", 
-   "oldfieldtype": "Link", 
-   "options": "Journal Entry", 
+   "allow_on_submit": 0, 
+   "fieldname": "reference_name", 
+   "fieldtype": "Dynamic Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Reference Name", 
+   "no_copy": 0, 
+   "options": "reference_type", 
    "permlevel": 0, 
+   "precision": "", 
    "print_hide": 0, 
-   "search_index": 1
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "col_break3", 
    "fieldtype": "Column Break", 
-   "permlevel": 0
-  }, 
-  {
-   "fieldname": "against_sales_order", 
-   "fieldtype": "Link", 
-   "label": "Against Sales Order", 
-   "options": "Sales Order", 
-   "permlevel": 0
-  }, 
-  {
-   "fieldname": "against_purchase_order", 
-   "fieldtype": "Link", 
-   "label": "Against Purchase Order", 
-   "options": "Purchase Order", 
-   "permlevel": 0
-  }, 
-  {
-   "fieldname": "against_expense_claim", 
-   "fieldtype": "Link", 
-   "label": "Against Expense Claim", 
-   "options": "Expense Claim", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "no_copy": 0, 
    "permlevel": 0, 
-   "precision": ""
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "is_advance", 
    "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Is Advance", 
    "no_copy": 1, 
    "oldfieldname": "is_advance", 
    "oldfieldtype": "Select", 
    "options": "No\nYes", 
    "permlevel": 0, 
-   "print_hide": 1
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }, 
   {
+   "allow_on_submit": 0, 
    "fieldname": "against_account", 
    "fieldtype": "Text", 
    "hidden": 1, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
    "label": "Against Account", 
    "no_copy": 1, 
    "oldfieldname": "against_account", 
    "oldfieldtype": "Text", 
    "permlevel": 0, 
-   "print_hide": 1
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }
  ], 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
  "idx": 1, 
+ "in_create": 0, 
+ "in_dialog": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
  "istable": 1, 
- "modified": "2015-02-19 01:07:00.388689", 
+ "modified": "2015-08-11 10:44:11.432623", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Journal Entry Account", 
  "owner": "Administrator", 
- "permissions": []
+ "permissions": [], 
+ "read_only": 0, 
+ "read_only_onload": 0
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index bcca0f2..933570f 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -34,8 +34,8 @@
 				t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
 				and t2.party_type = %(party_type)s and t2.party = %(party)s
 				and t2.account = %(account)s and {dr_or_cr} > 0
-				and ifnull(t2.against_voucher, '')='' and ifnull(t2.against_invoice, '')=''
-				and ifnull(t2.against_jv, '')='' {cond}
+				and ifnull(t2.reference_type, '')=''
+				{cond}
 				and (CASE
 					WHEN t1.voucher_type in ('Debit Note', 'Credit Note')
 					THEN 1=1
@@ -190,7 +190,7 @@
 				if flt(p.allocated_amount) > flt(p.amount):
 					frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
 						.format(p.idx, p.allocated_amount, p.amount))
-				
+
 				invoice_outstanding = unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)
 				if flt(p.allocated_amount) - invoice_outstanding > 0.009:
 					frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
diff --git a/erpnext/accounts/doctype/payment_tool/payment_tool.py b/erpnext/accounts/doctype/payment_tool/payment_tool.py
index 6a002af..4edbebd 100644
--- a/erpnext/accounts/doctype/payment_tool/payment_tool.py
+++ b/erpnext/accounts/doctype/payment_tool/payment_tool.py
@@ -12,13 +12,6 @@
 	def make_journal_entry(self):
 		from erpnext.accounts.utils import get_balance_on
 		total_payment_amount = 0.00
-		invoice_voucher_type = {
-			'Sales Invoice': 'against_invoice',
-			'Purchase Invoice': 'against_voucher',
-			'Journal Entry': 'against_jv',
-			'Sales Order': 'against_sales_order',
-			'Purchase Order': 'against_purchase_order',
-		}
 
 		jv = frappe.new_doc('Journal Entry')
 		jv.voucher_type = 'Journal Entry'
@@ -41,7 +34,8 @@
 				d1.party = self.party
 				d1.balance = get_balance_on(self.party_account)
 				d1.set("debit" if self.received_or_paid=="Paid" else "credit", flt(v.payment_amount))
-				d1.set(invoice_voucher_type.get(v.against_voucher_type), v.against_voucher_no)
+				d1.set("reference_type", v.against_voucher_type)
+				d1.set("reference_name", v.against_voucher_no)
 				d1.set('is_advance', 'Yes' if v.against_voucher_type in ['Sales Order', 'Purchase Order'] else 'No')
 				total_payment_amount = flt(total_payment_amount) + flt(d1.debit) - flt(d1.credit)
 
diff --git a/erpnext/accounts/doctype/payment_tool/test_payment_tool.py b/erpnext/accounts/doctype/payment_tool/test_payment_tool.py
index a4ff333..321986c 100644
--- a/erpnext/accounts/doctype/payment_tool/test_payment_tool.py
+++ b/erpnext/accounts/doctype/payment_tool/test_payment_tool.py
@@ -23,10 +23,11 @@
 
 		# Create SO with partial outstanding
 		so1 = make_sales_order(customer="_Test Customer 3", qty=10, rate=100)
-		
+
 		self.create_against_jv(jv_test_records[0], {
 			"party": "_Test Customer 3",
-			"against_sales_order": so1.name,
+			"reference_type": "Sales Order",
+			"reference_name": so1.name,
 			"is_advance": "Yes"
 		})
 
@@ -36,7 +37,8 @@
 
 		self.create_against_jv(jv_test_records[0], {
 			"party": "_Test Customer 3",
-			"against_sales_order": so2.name,
+			"reference_type": "Sales Order",
+			"reference_name": so2.name,
 			"credit": 1000,
 			"is_advance": "Yes"
 		})
@@ -52,7 +54,8 @@
 
 		self.create_against_jv(jv_test_records[0], {
 			"party": "_Test Customer 3",
-			"against_invoice": si1.name
+			"reference_type": si1.doctype,
+			"reference_name": si1.name
 		})
 		#Create SI with no outstanding
 		si2 = self.create_voucher(si_test_records[0], {
@@ -62,7 +65,8 @@
 
 		self.create_against_jv(jv_test_records[0], {
 			"party": "_Test Customer 3",
-			"against_invoice": si2.name,
+			"reference_type": si2.doctype,
+			"reference_name": si2.name,
 			"credit": 561.80
 		})
 
@@ -125,7 +129,7 @@
 	def make_voucher_for_party(self, args, expected_outstanding):
 		#Make Journal Entry for Party
 		payment_tool_doc = frappe.new_doc("Payment Tool")
-		
+
 		for k, v in args.items():
 			payment_tool_doc.set(k, v)
 
@@ -153,29 +157,12 @@
 
 		new_jv = paytool.make_journal_entry()
 
-		#Create a list of expected values as [party account, payment against, against_jv, against_invoice,
-		#against_voucher, against_sales_order, against_purchase_order]
-		expected_values = [
-			[paytool.party_account, paytool.party, 100.00, expected_outstanding.get("Journal Entry")[0], None, None, None, None],
-			[paytool.party_account, paytool.party, 100.00, None, expected_outstanding.get("Sales Invoice")[0], None, None, None],
-			[paytool.party_account, paytool.party, 100.00, None, None, expected_outstanding.get("Purchase Invoice")[0], None, None],
-			[paytool.party_account, paytool.party, 100.00, None, None, None, expected_outstanding.get("Sales Order")[0], None],
-			[paytool.party_account, paytool.party, 100.00, None, None, None, None, expected_outstanding.get("Purchase Order")[0]]
-		]
-
 		for jv_entry in new_jv.get("accounts"):
 			if paytool.party_account == jv_entry.get("account") and paytool.party == jv_entry.get("party"):
-				row = [
-					jv_entry.get("account"),
-					jv_entry.get("party"),
-					jv_entry.get("debit" if paytool.party_type=="Supplier" else "credit"),
-					jv_entry.get("against_jv"),
-					jv_entry.get("against_invoice"),
-					jv_entry.get("against_voucher"),
-					jv_entry.get("against_sales_order"),
-					jv_entry.get("against_purchase_order"),
-				]
-				self.assertTrue(row in expected_values)
+				self.assertEquals(100.00,
+					jv_entry.get("debit" if paytool.party_type=="Supplier" else "credit"))
+				self.assertEquals(jv_entry.reference_name,
+					expected_outstanding[jv_entry.reference_type][0])
 
 		self.assertEquals(new_jv.get("cheque_no"), paytool.reference_no)
 		self.assertEquals(new_jv.get("cheque_date"), paytool.reference_date)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 8e91250..6257865 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -21,16 +21,15 @@
 
 		// Show / Hide button
 		this.show_general_ledger();
-		
+
 		if(!doc.is_return) {
 			if(doc.docstatus==1) {
 				if(doc.outstanding_amount > 0) {
-					this.frm.add_custom_button(__('Make Payment Entry'), this.make_bank_entry);
+					this.frm.add_custom_button(__('Payment'), this.make_bank_entry).addClass("btn-primary");
 				}
-				
-				cur_frm.add_custom_button(__('Make Debit Note'), this.make_debit_note);
+				cur_frm.add_custom_button(__('Debit Note'), this.make_debit_note);
 			}
-			
+
 			if(doc.docstatus===0) {
 				cur_frm.add_custom_button(__('From Purchase Order'), function() {
 					frappe.model.map_current_doc({
@@ -102,7 +101,7 @@
 			if(row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt)
 		})
 	},
-	
+
 	make_debit_note: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 00ea6ae..132cb10 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -41,8 +41,8 @@
 			self.po_required()
 			self.pr_required()
 			self.validate_supplier_invoice()
-			self.validate_advance_jv("advances", "purchase_order")
-			
+			self.validate_advance_jv("Purchase Order")
+
 		self.check_active_purchase_items()
 		self.check_conversion_rate()
 		self.validate_credit_to_acc()
@@ -233,7 +233,7 @@
 			self.update_against_document_in_jv()
 			self.update_prevdoc_status()
 			self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
-			
+
 		self.update_project()
 
 	def make_gl_entries(self):
@@ -365,7 +365,7 @@
 	def on_cancel(self):
 		if not self.is_return:
 			from erpnext.accounts.utils import remove_against_link_from_jv
-			remove_against_link_from_jv(self.doctype, self.name, "against_voucher")
+			remove_against_link_from_jv(self.doctype, self.name)
 
 			self.update_prevdoc_status()
 			self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
@@ -413,4 +413,4 @@
 @frappe.whitelist()
 def make_debit_note(source_name, target_doc=None):
 	from erpnext.controllers.sales_and_purchase_return import make_return_doc
-	return make_return_doc("Purchase Invoice", source_name, target_doc)
\ No newline at end of file
+	return make_return_doc("Purchase Invoice", source_name, target_doc)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 017ab3a..caf741e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -40,14 +40,17 @@
 		this._super();
 
 		cur_frm.dashboard.reset();
-		
+
 		this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
-		
+
 		this.show_general_ledger();
-		
+
 		if(doc.update_stock) this.show_stock_ledger();
-		
+
 		if(doc.docstatus==1 && !doc.is_return) {
+			cur_frm.add_custom_button(doc.update_stock ? __('Sales Return') : __('Credit Note'),
+				this.make_sales_return);
+
 			if(cint(doc.update_stock)!=1) {
 				// show Make Delivery Note button only if Sales Invoice is not created from Delivery Note
 				var from_delivery_note = false;
@@ -57,16 +60,13 @@
 					});
 
 				if(!from_delivery_note) {
-					cur_frm.add_custom_button(__('Make Delivery'), cur_frm.cscript['Make Delivery Note'])
+					cur_frm.add_custom_button(__('Delivery'), cur_frm.cscript['Make Delivery Note']).addClass("btn-primary");
 				}
 			}
 
 			if(doc.outstanding_amount!=0 && !cint(doc.is_return)) {
-				cur_frm.add_custom_button(__('Make Payment Entry'), cur_frm.cscript.make_bank_entry);
+				cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry).addClass("btn-primary");
 			}
-			
-			cur_frm.add_custom_button(doc.update_stock ? __('Make Sales Return') : __('Make Credit Note'), 
-				this.make_sales_return);
 		}
 
 		// Show buttons only when pos view is active
@@ -201,7 +201,7 @@
 	items_on_form_rendered: function() {
 		erpnext.setup_serial_no();
 	},
-	
+
 	make_sales_return: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_sales_return",
@@ -390,4 +390,4 @@
 			['Account', 'account_type', '=', 'Receivable']
 		]
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 6d76b53..4285eb8 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -46,7 +46,7 @@
 		self.validate_debit_to_acc()
 		self.validate_fixed_asset_account()
 		self.clear_unallocated_advances("Sales Invoice Advance", "advances")
-		self.validate_advance_jv("advances", "sales_order")
+		self.validate_advance_jv("Sales Order")
 		self.add_remarks()
 		self.validate_write_off_account()
 
@@ -105,7 +105,7 @@
 		self.check_stop_sales_order("sales_order")
 
 		from erpnext.accounts.utils import remove_against_link_from_jv
-		remove_against_link_from_jv(self.doctype, self.name, "against_invoice")
+		remove_against_link_from_jv(self.doctype, self.name)
 
 		if not self.is_return:
 			self.update_status_updater_args()
@@ -420,7 +420,7 @@
 		for d in self.get_item_list():
 			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and d.warehouse and flt(d['qty']):
 				self.update_reserved_qty(d)
-				
+
 				incoming_rate = 0
 				if cint(self.is_return) and self.return_against and self.docstatus==1:
 					incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code,
@@ -447,7 +447,7 @@
 
 			if update_outstanding == "No":
 				from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
-				update_outstanding_amt(self.debit_to, "Customer", self.customer, 
+				update_outstanding_amt(self.debit_to, "Customer", self.customer,
 					self.doctype, self.return_against if cint(self.is_return) else self.name)
 
 			if repost_future_gle and cint(self.update_stock) \
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 67f4a8e..c7a992c 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -391,7 +391,8 @@
 			import test_records as jv_test_records
 
 		jv = frappe.get_doc(frappe.copy_doc(jv_test_records[0]))
-		jv.get("accounts")[0].against_invoice = w.name
+		jv.get("accounts")[0].reference_type = w.doctype
+		jv.get("accounts")[0].reference_name = w.name
 		jv.insert()
 		jv.submit()
 
@@ -656,17 +657,17 @@
 		si.load_from_db()
 
 		self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
-			where against_invoice=%s""", si.name))
+			where reference_name=%s""", si.name))
 
 		self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
-			where against_invoice=%s and credit=300""", si.name))
+			where reference_name=%s and credit=300""", si.name))
 
 		self.assertEqual(si.outstanding_amount, 261.8)
 
 		si.cancel()
 
 		self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
-			where against_invoice=%s""", si.name))
+			where reference_name=%s""", si.name))
 
 	def test_recurring_invoice(self):
 		from erpnext.controllers.tests.test_recurring_document import test_recurring_document
@@ -728,68 +729,67 @@
 
 		# hack! because stock ledger entires are already inserted and are not rolled back!
 		self.assertRaises(SerialNoDuplicateError, si.cancel)
-		
+
 	def test_invoice_due_date_against_customers_credit_days(self):
 		# set customer's credit days
 		frappe.db.set_value("Customer", "_Test Customer", "credit_days_based_on", "Fixed Days")
 		frappe.db.set_value("Customer", "_Test Customer", "credit_days", 10)
-		
+
 		si = create_sales_invoice()
 		self.assertEqual(si.due_date, add_days(nowdate(), 10))
-		
+
 		# set customer's credit days is last day of the next month
 		frappe.db.set_value("Customer", "_Test Customer", "credit_days_based_on", "Last Day of the Next Month")
-		
-		si1 = create_sales_invoice(posting_date="2015-07-05")		
+
+		si1 = create_sales_invoice(posting_date="2015-07-05")
 		self.assertEqual(si1.due_date, "2015-08-31")
-		
+
 	def test_return_sales_invoice(self):
 		set_perpetual_inventory()
-		
 		make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
-		
+
 		actual_qty_0 = get_qty_after_transaction()
-		
+
 		si = create_sales_invoice(qty=5, rate=500, update_stock=1)
 
 		actual_qty_1 = get_qty_after_transaction()
 		self.assertEquals(actual_qty_0 - 5, actual_qty_1)
-		
+
 		# outgoing_rate
-		outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Sales Invoice", 
+		outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Sales Invoice",
 			"voucher_no": si.name}, "stock_value_difference") / 5
-		
+
 		# return entry
 		si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1)
 
 		actual_qty_2 = get_qty_after_transaction()
-			
+
 		self.assertEquals(actual_qty_1 + 2, actual_qty_2)
-		
-		incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", 
-			{"voucher_type": "Sales Invoice", "voucher_no": si1.name}, 
+
+		incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
+			{"voucher_type": "Sales Invoice", "voucher_no": si1.name},
 			["incoming_rate", "stock_value_difference"])
-			
+
 		self.assertEquals(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
-		
-		
+
+
 		# Check gl entry
-		gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice", 
+		gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
 			"voucher_no": si1.name, "account": "_Test Warehouse - _TC"}, "debit")
-			
+
 		self.assertEquals(gle_warehouse_amount, stock_value_difference)
-		
-		party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice", 
+
+		party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
 			"voucher_no": si1.name, "account": "Debtors - _TC", "party": "_Test Customer"}, "credit")
-			
+
 		self.assertEqual(party_credited, 1000)
-		
+
 		# Check outstanding amount
 		self.assertFalse(si1.outstanding_amount)
 		self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500)
-		
+
 		set_perpetual_inventory(0)
-		
+
 	def test_discount_on_net_total(self):
 		si = frappe.copy_doc(test_records[2])
 		si.apply_discount_on = "Net Total"
@@ -798,7 +798,7 @@
 
 		expected_values = {
 			"keys": ["price_list_rate", "discount_percentage", "rate", "amount",
-				"base_price_list_rate", "base_rate", "base_amount", 
+				"base_price_list_rate", "base_rate", "base_amount",
 				"net_rate", "base_net_rate", "net_amount", "base_net_amount"],
 			"_Test Item Home Desktop 100": [50, 0, 50, 500, 50, 50, 500, 25, 25, 250, 250],
 			"_Test Item Home Desktop 200": [150, 0, 150, 750, 150, 150, 750, 75, 75, 375, 375],
@@ -821,7 +821,7 @@
 
 		# check tax calculation
 		expected_values = {
-			"keys": ["tax_amount", "tax_amount_after_discount_amount", 
+			"keys": ["tax_amount", "tax_amount_after_discount_amount",
 				"base_tax_amount_after_discount_amount"],
 			"_Test Account Shipping Charges - _TC": [100, 100, 100],
 			"_Test Account Customs Duty - _TC": [62.5, 62.5, 62.5],
@@ -836,12 +836,12 @@
 		for d in si.get("taxes"):
 			for i, k in enumerate(expected_values["keys"]):
 				self.assertEquals(d.get(k), expected_values[d.account_head][i])
-				
-		
+
+
 		self.assertEquals(si.total_taxes_and_charges, 234.44)
 		self.assertEquals(si.base_grand_total, 859.44)
 		self.assertEquals(si.grand_total, 859.44)
-		
+
 
 def create_sales_invoice(**args):
 	si = frappe.new_doc("Sales Invoice")
diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
index 699d684..604bc56 100644
--- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
+++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
@@ -15,21 +15,19 @@
 	entries = get_entries(filters)
 	invoice_posting_date_map = get_invoice_posting_date_map(filters)
 	against_date = ""
-	outstanding_amount = 0.0
 
 	data = []
 	for d in entries:
-		if d.against_voucher:
-			against_date = d.against_voucher and invoice_posting_date_map[d.against_voucher] or ""
+		against_date = invoice_posting_date_map[d.reference_name] or ""
+		if d.reference_type=="Purchase Invoice":
 			payment_amount = flt(d.debit) or -1 * flt(d.credit)
 		else:
-			against_date = d.against_invoice and invoice_posting_date_map[d.against_invoice] or ""
 			payment_amount = flt(d.credit) or -1 * flt(d.debit)
 
-		row = [d.name, d.party_type, d.party, d.posting_date, d.against_voucher or d.against_invoice,
+		row = [d.name, d.party_type, d.party, d.posting_date, d.reference_name,
 			against_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
 
-		if d.against_voucher or d.against_invoice:
+		if d.reference_name:
 			row += get_ageing_data(30, 60, 90, d.posting_date, against_date, payment_amount)
 		else:
 			row += ["", "", "", "", ""]
@@ -82,7 +80,7 @@
 def get_entries(filters):
 	conditions = get_conditions(filters)
 	entries =  frappe.db.sql("""select jv.name, jvd.party_type, jvd.party, jv.posting_date,
-		jvd.against_voucher, jvd.against_invoice, jvd.debit, jvd.credit,
+		jvd.reference_type, jvd.reference_name, jvd.debit, jvd.credit,
 		jv.cheque_no, jv.cheque_date, jv.remark
 		from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
 		where jvd.parent = jv.name and jv.docstatus=1 %s order by jv.name DESC""" %
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 298ff8e..f41d19d 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -142,13 +142,6 @@
 	for d in args:
 		check_if_jv_modified(d)
 		validate_allocated_amount(d)
-		against_fld = {
-			'Journal Entry' : 'against_jv',
-			'Sales Invoice' : 'against_invoice',
-			'Purchase Invoice' : 'against_voucher'
-		}
-
-		d['against_fld'] = against_fld[d['against_voucher_type']]
 
 		# cancel JV
 		jv_obj = frappe.get_doc('Journal Entry', d['voucher_no'])
@@ -173,8 +166,7 @@
 		select t2.{dr_or_cr} from `tabJournal Entry` t1, `tabJournal Entry Account` t2
 		where t1.name = t2.parent and t2.account = %(account)s
 		and t2.party_type = %(party_type)s and t2.party = %(party)s
-		and ifnull(t2.against_voucher, '')=''
-		and ifnull(t2.against_invoice, '')='' and ifnull(t2.against_jv, '')=''
+		and ifnull(t2.reference_type, '') in ("", "Sales Order", "Purchase Order")
 		and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
 		and t1.docstatus=1 """.format(dr_or_cr = args.get("dr_or_cr")), args)
 
@@ -193,7 +185,12 @@
 	"""
 	jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0]
 	jv_detail.set(d["dr_or_cr"], d["allocated_amt"])
-	jv_detail.set(d["against_fld"], d["against_voucher"])
+
+	original_reference_type = jv_detail.reference_type
+	original_reference_name = jv_detail.reference_name
+
+	jv_detail.set("reference_type", d["against_voucher_type"])
+	jv_detail.set("reference_name", d["against_voucher"])
 
 	if d['allocated_amt'] < d['unadjusted_amt']:
 		jvd = frappe.db.sql("""select cost_center, balance, against_account, is_advance
@@ -208,6 +205,8 @@
 		ch.set(d['dr_or_cr'], flt(d['unadjusted_amt']) - flt(d['allocated_amt']))
 		ch.set(d['dr_or_cr']== 'debit' and 'credit' or 'debit', 0)
 		ch.against_account = cstr(jvd[0][2])
+		ch.reference_type = original_reference_type
+		ch.reference_name = original_reference_name
 		ch.is_advance = cstr(jvd[0][3])
 		ch.docstatus = 1
 
@@ -215,15 +214,16 @@
 	jv_obj.flags.ignore_validate_update_after_submit = True
 	jv_obj.save()
 
-def remove_against_link_from_jv(ref_type, ref_no, against_field):
+def remove_against_link_from_jv(ref_type, ref_no):
 	linked_jv = frappe.db.sql_list("""select parent from `tabJournal Entry Account`
-		where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no))
+		where reference_type=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no))
 
 	if linked_jv:
-		frappe.db.sql("""update `tabJournal Entry Account` set `%s`=null,
+		frappe.db.sql("""update `tabJournal Entry Account`
+			set reference_type=null, reference_name = null,
 			modified=%s, modified_by=%s
-			where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"),
-			(now(), frappe.session.user, ref_no))
+			where reference_type=%s and reference_name=%s
+			and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no))
 
 		frappe.db.sql("""update `tabGL Entry`
 			set against_voucher_type=null, against_voucher=null,
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 09a0e91..a5cd6ce 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -5,6 +5,14 @@
 
 {% include 'buying/doctype/purchase_common/purchase_common.js' %};
 
+frappe.ui.form.on("Purchase Order", {
+	onload: function(frm) {
+		erpnext.queries.setup_queries(frm, "Warehouse", function() {
+			return erpnext.queries.warehouse(frm.doc);
+		});
+	}
+});
+
 erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
 	refresh: function(doc, cdt, cdn) {
 		var me = this;
@@ -12,31 +20,38 @@
 		// this.frm.dashboard.reset();
 
 		if(doc.docstatus == 1 && doc.status != 'Stopped') {
+
+			if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100)
+				cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Purchase Order']);
+
+			if(flt(doc.per_billed)==0) {
+				cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry);
+			}
+
 			if(flt(doc.per_received, 2) < 100) {
-				cur_frm.add_custom_button(__('Make Purchase Receipt'), this.make_purchase_receipt);
-				
+				cur_frm.add_custom_button(__('Receive'), this.make_purchase_receipt).addClass("btn-primary");
+
 				if(doc.is_subcontracted==="Yes") {
 					cur_frm.add_custom_button(__('Transfer Material to Supplier'), this.make_stock_entry);
 				}
 			}
+
 			if(flt(doc.per_billed, 2) < 100)
-				cur_frm.add_custom_button(__('Make Invoice'), this.make_purchase_invoice);
-			
-			if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100)
-				cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Purchase Order']);
+				cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice);
+
 
 		} else if(doc.docstatus===0) {
 			cur_frm.cscript.add_from_mappers();
 		}
 
 		if(doc.docstatus == 1 && doc.status == 'Stopped')
-			cur_frm.add_custom_button(__('Unstop Purchase Order'), cur_frm.cscript['Unstop Purchase Order']);
+			cur_frm.add_custom_button(__('Unstop'), cur_frm.cscript['Unstop Purchase Order']);
 	},
 
 	make_stock_entry: function() {
 		var items = $.map(cur_frm.doc.items, function(d) { return d.bom ? d.item_code : false; });
 		var me = this;
-		
+
 		if(items.length===1) {
 			me._make_stock_entry(items[0]);
 			return;
@@ -126,7 +141,21 @@
 	items_add: function(doc, cdt, cdn) {
 		var row = frappe.get_doc(cdt, cdn);
 		this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]);
+	},
+
+	make_bank_entry: function() {
+		return frappe.call({
+			method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_from_purchase_order",
+			args: {
+				"purchase_order": cur_frm.doc.name
+			},
+			callback: function(r) {
+				var doclist = frappe.model.sync(r.message);
+				frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
+			}
+		});
 	}
+
 });
 
 // for backward compatibility: combine new and previous states
diff --git a/erpnext/change_log/current/journal_entry_rename.md b/erpnext/change_log/current/journal_entry_rename.md
new file mode 100644
index 0000000..9bd1b66
--- /dev/null
+++ b/erpnext/change_log/current/journal_entry_rename.md
@@ -0,0 +1 @@
+- For referencing a line in **Journal Entry**, now you can reference by the **Reference Type** and **Reference Name** columns, instead of "Against Sales Invoice", "Against Purchase Invoice", etc.
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 915d294..ecd9e1a 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -211,29 +211,32 @@
 			and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
 
 	def get_advances(self, account_head, party_type, party, child_doctype, parentfield, dr_or_cr, against_order_field):
-		so_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
-		cond = ""
-		if so_list:
-			cond = "or (ifnull(t2.%s, '')  in (%s))" % ("against_" + against_order_field, ', '.join(['%s']*len(so_list)))
+		"""Returns list of advances against Account, Party, Reference"""
+		order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
+
+		if not order_list:
+			return
+
+		in_placeholder = ', '.join(['%s'] * len(order_list))
+
+		# conver sales_order to "Sales Order"
+		reference_type = against_order_field.replace("_", " ").title()
 
 		res = frappe.db.sql("""
 			select
-				t1.name as jv_no, t1.remark, t2.{0} as amount, t2.name as jv_detail_no, `against_{1}` as against_order
+				t1.name as jv_no, t1.remark, t2.{0} as amount, t2.name as jv_detail_no,
+				reference_name as against_order
 			from
 				`tabJournal Entry` t1, `tabJournal Entry Account` t2
 			where
 				t1.name = t2.parent and t2.account = %s
-				and t2.party_type=%s and t2.party=%s
+				and t2.party_type = %s and t2.party = %s
 				and t2.is_advance = 'Yes' and t1.docstatus = 1
-				and ((
-						ifnull(t2.against_voucher, '')  = ''
-						and ifnull(t2.against_invoice, '')  = ''
-						and ifnull(t2.against_jv, '')  = ''
-						and ifnull(t2.against_sales_order, '')  = ''
-						and ifnull(t2.against_purchase_order, '')  = ''
-				) {2})
-			order by t1.posting_date""".format(dr_or_cr, against_order_field, cond),
-			[account_head, party_type, party] + so_list, as_dict=1)
+				and (
+					ifnull(t2.reference_type, '')=''
+					or (t2.reference_type = %s and ifnull(t2.reference_name, '') in ({1})))
+			order by t1.posting_date""".format(dr_or_cr, in_placeholder),
+			[account_head, party_type, party, reference_type] + order_list, as_dict=1)
 
 		self.set(parentfield, [])
 		for d in res:
@@ -246,25 +249,26 @@
 				"allocated_amount": flt(d.amount) if d.against_order else 0
 			})
 
-	def validate_advance_jv(self, advance_table_fieldname, against_order_field):
+	def validate_advance_jv(self, reference_type):
+		against_order_field = frappe.scrub(reference_type)
 		order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
 		if order_list:
 			account = self.get("debit_to" if self.doctype=="Sales Invoice" else "credit_to")
 
-			jv_against_order = frappe.db.sql("""select parent, %s as against_order
+			jv_against_order = frappe.db.sql("""select parent, reference_name as against_order
 				from `tabJournal Entry Account`
 				where docstatus=1 and account=%s and ifnull(is_advance, 'No') = 'Yes'
-				and ifnull(against_sales_order, '') in (%s)
-				group by parent, against_sales_order""" %
-				("against_" + against_order_field, '%s', ', '.join(['%s']*len(order_list))),
-				tuple([account] + order_list), as_dict=1)
+				and reference_type=%s
+				and ifnull(reference_name, '') in ({0})
+				group by parent, reference_name""".format(', '.join(['%s']*len(order_list))),
+					tuple([account, reference_type] + order_list), as_dict=1)
 
 			if jv_against_order:
 				order_jv_map = {}
 				for d in jv_against_order:
 					order_jv_map.setdefault(d.against_order, []).append(d.parent)
 
-				advance_jv_against_si = [d.journal_entry for d in self.get(advance_table_fieldname)]
+				advance_jv_against_si = [d.journal_entry for d in self.get("advances")]
 
 				for order, jv_list in order_jv_map.items():
 					for jv in jv_list:
@@ -318,10 +322,8 @@
 	def set_total_advance_paid(self):
 		if self.doctype == "Sales Order":
 			dr_or_cr = "credit"
-			against_field = "against_sales_order"
 		else:
 			dr_or_cr = "debit"
-			against_field = "against_purchase_order"
 
 		advance_paid = frappe.db.sql("""
 			select
@@ -329,8 +331,10 @@
 			from
 				`tabJournal Entry Account`
 			where
-				{against_field} = %s and docstatus = 1 and is_advance = "Yes" """.format(dr_or_cr=dr_or_cr, \
-					against_field=against_field), self.name)
+				reference_type = %s and
+				reference_name = %s and
+				docstatus = 1 and is_advance = "Yes" """.format(dr_or_cr=dr_or_cr),
+					(self.doctype, self.name))
 
 		if advance_paid:
 			advance_paid = flt(advance_paid[0][0], self.precision("advance_paid"))
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index a56929d..1d405da 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -24,13 +24,15 @@
 					var d1 = frappe.model.add_child(jv, 'Journal Entry Account', 'accounts');
 					d1.debit = expense[i].sanctioned_amount;
 					d1.account = expense[i].default_account;
-					d1.against_expense_claim = cur_frm.doc.name;
+					d1.reference_type = cur_frm.doc.doctype;
+					d1.reference_name = cur_frm.doc.name;
 				}
 
 				// credit to bank
 				var d1 = frappe.model.add_child(jv, 'Journal Entry Account', 'accounts');
 				d1.credit = cur_frm.doc.total_sanctioned_amount;
-				d1.against_expense_claim = cur_frm.doc.name;
+				d1.reference_type = cur_frm.doc.doctype;
+				d1.reference_name = cur_frm.doc.name;
 				if(r.message) {
 					d1.account = r.message.account;
 					d1.balance = r.message.balance;
@@ -179,5 +181,5 @@
 		filters:{
 			'project': doc.project
 		}
-	}	
-}
\ No newline at end of file
+	}
+}
diff --git a/erpnext/patches/v5_4/cleanup_journal_entry.py b/erpnext/patches/v5_4/cleanup_journal_entry.py
new file mode 100644
index 0000000..9968e3c
--- /dev/null
+++ b/erpnext/patches/v5_4/cleanup_journal_entry.py
@@ -0,0 +1,14 @@
+import frappe
+
+def execute():
+	for doctype, fieldname in (
+		("Sales Invoice", "against_invoice"),
+		("Purchase Invoice", "against_voucher"),
+		("Sales Order", "against_sales_order"),
+		("Purchase Order", "against_purchase_order"),
+		("Journal Entry", "against_jv"),
+		("Expense Claim", "against_expense_claim"),
+	):
+		frappe.db.update("""update `tabJournal Entry Detail`
+			set reference_type=%s and reference_name={0} where ifnull({0}, '') != ''
+		""".format(fieldname), doctype)
diff --git a/erpnext/public/js/controllers/stock_controller.js b/erpnext/public/js/controllers/stock_controller.js
index f5f7aa0..ff5cf53 100644
--- a/erpnext/public/js/controllers/stock_controller.js
+++ b/erpnext/public/js/controllers/stock_controller.js
@@ -12,31 +12,8 @@
 	},
 
 	setup_warehouse_query: function() {
-		var me = this;
-		var warehouse_query_method = function() {
+		erpnext.queries.setup_queries(me.frm, "Warehouse", function() {
 			return erpnext.queries.warehouse(me.frm.doc);
-		};
-
-		var _set_warehouse_query = function(doctype, parentfield) {
-			var warehouse_link_fields = frappe.meta.get_docfields(doctype, me.frm.doc.name,
-				{"fieldtype": "Link", "options": "Warehouse"});
-			$.each(warehouse_link_fields, function(i, df) {
-				if(parentfield) {
-					me.frm.set_query(df.fieldname, parentfield, warehouse_query_method);
-				} else {
-					me.frm.set_query(df.fieldname, warehouse_query_method);
-				}
-			});
-		};
-
-		_set_warehouse_query(me.frm.doc.doctype);
-
-		// warehouse field in tables
-		var table_fields = frappe.meta.get_docfields(me.frm.doc.doctype, me.frm.doc.name,
-			{"fieldtype": "Table"});
-
-		$.each(table_fields, function(i, df) {
-			_set_warehouse_query(df.options, df.fieldname);
 		});
 	},
 
diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js
index b487c23..12307fb 100644
--- a/erpnext/public/js/queries.js
+++ b/erpnext/public/js/queries.js
@@ -75,3 +75,26 @@
 		}
 	}
 });
+
+erpnext.queries.setup_queries = function(frm, options, query_fn) {
+	var me = this;
+	var set_query = function(doctype, parentfield) {
+		var link_fields = frappe.meta.get_docfields(doctype, frm.doc.name,
+			{"fieldtype": "Link", "options": options});
+		$.each(link_fields, function(i, df) {
+			if(parentfield) {
+				frm.set_query(df.fieldname, parentfield, query_fn);
+			} else {
+				frm.set_query(df.fieldname, query_fn);
+			}
+		});
+	};
+
+	set_query(frm.doc.doctype);
+
+	// warehouse field in tables
+	$.each(frappe.meta.get_docfields(frm.doc.doctype, frm.doc.name, {"fieldtype": "Table"}),
+		function(i, df) {
+			set_query(df.options, df.fieldname);
+		});
+}
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index d06d550..4a047e4 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -3,6 +3,14 @@
 
 {% include 'selling/sales_common.js' %}
 
+frappe.ui.form.on("Sales Order", {
+	onload: function(frm) {
+		erpnext.queries.setup_queries(frm, "Warehouse", function() {
+			return erpnext.queries.warehouse(frm.doc);
+		});
+	}
+});
+
 erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
 	refresh: function(doc, dt, dn) {
 		this._super();
@@ -16,29 +24,32 @@
 				// cur_frm.dashboard.add_progress(cint(doc.per_billed) + __("% Billed"),
 				// 	doc.per_billed);
 
-				// delivery note
-				if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
-					cur_frm.add_custom_button(__('Make Delivery'), this.make_delivery_note);
-
 				// indent
 				if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
-					cur_frm.add_custom_button(__('Make ') + __('Material Request'),
-						this.make_material_request);
+					cur_frm.add_custom_button(__('Material Request'), this.make_material_request);
 
-				// sales invoice
-				if(flt(doc.per_billed, 2) < 100) {
-					cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
+				if(flt(doc.per_billed)==0) {
+					cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry);
 				}
 
 				// stop
 				if(flt(doc.per_delivered, 2) < 100 || doc.per_billed < 100)
 					cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Sales Order'])
 
-						// maintenance
-						if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
-							cur_frm.add_custom_button(__('Make Maint. Visit'), this.make_maintenance_visit);
-							cur_frm.add_custom_button(__('Make Maint. Schedule'), this.make_maintenance_schedule);
-						}
+					// maintenance
+					if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
+						cur_frm.add_custom_button(__('Maint. Visit'), this.make_maintenance_visit);
+						cur_frm.add_custom_button(__('Maint. Schedule'), this.make_maintenance_schedule);
+					}
+
+					// delivery note
+					if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
+						cur_frm.add_custom_button(__('Delivery'), this.make_delivery_note).addClass("btn-primary");
+
+					// sales invoice
+					if(flt(doc.per_billed, 2) < 100) {
+						cur_frm.add_custom_button(__('Invoice'), this.make_sales_invoice).addClass("btn-primary");
+					}
 
 			} else {
 				// un-stop
@@ -122,6 +133,20 @@
 			frm: cur_frm
 		})
 	},
+
+	make_bank_entry: function() {
+		return frappe.call({
+			method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_from_sales_order",
+			args: {
+				"sales_order": cur_frm.doc.name
+			},
+			callback: function(r) {
+				var doclist = frappe.model.sync(r.message);
+				frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
+			}
+		});
+	}
+
 });
 
 // for backward compatibility: combine new and previous states
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 94356da..e7ede65 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -8,28 +8,28 @@
 erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend({
 	refresh: function(doc, dt, dn) {
 		this._super();
-		
+
 		if (!doc.is_return) {
 			if(doc.__onload && !doc.__onload.billing_complete && doc.docstatus==1) {
 				// show Make Invoice button only if Delivery Note is not created from Sales Invoice
 				var from_sales_invoice = false;
 				from_sales_invoice = cur_frm.doc.items.some(function(item) {
-						return item.against_sales_invoice ? true : false;
-					});
+					return item.against_sales_invoice ? true : false;
+				});
 
 				if(!from_sales_invoice)
-					cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
+					cur_frm.add_custom_button(__('Invoice'), this.make_sales_invoice).addClass("btn-primary");
 			}
 
 			if(flt(doc.per_installed, 2) < 100 && doc.docstatus==1)
-				cur_frm.add_custom_button(__('Make Installation Note'), this.make_installation_note);
+				cur_frm.add_custom_button(__('Installation Note'), this.make_installation_note);
 
 			if (doc.docstatus==1) {
-				cur_frm.add_custom_button(__('Make Sales Return'), this.make_sales_return);
+				cur_frm.add_custom_button(__('Sales Return'), this.make_sales_return);
 			}
 
 			if(doc.docstatus==0 && !doc.__islocal) {
-				cur_frm.add_custom_button(__('Make Packing Slip'),
+				cur_frm.add_custom_button(__('Packing Slip'),
 					cur_frm.cscript['Make Packing Slip'], frappe.boot.doctype_icons["Packing Slip"]);
 			}
 
@@ -51,15 +51,15 @@
 					});
 			}
 		}
-		
+
 		if (doc.docstatus==1) {
 			this.show_stock_ledger();
 			if (cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
 				this.show_general_ledger();
 			}
 		}
-		
-			
+
+
 
 		erpnext.stock.delivery_note.set_print_hide(doc, dt, dn);
 
@@ -81,7 +81,7 @@
 			frm: cur_frm
 		});
 	},
-	
+
 	make_sales_return: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_return",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index fcaf9f8..38b054c 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -50,16 +50,15 @@
 						})
 				});
 			}
-			
+
 			if(this.frm.doc.docstatus == 1) {
+				cur_frm.add_custom_button(__('Return'), this.make_purchase_return);
 				if(this.frm.doc.__onload && !this.frm.doc.__onload.billing_complete) {
-					cur_frm.add_custom_button(__('Make Purchase Invoice'), this.make_purchase_invoice);
+					cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice).addClass("btn-primary");
 				}
-			
-				cur_frm.add_custom_button(__('Make Purchase Return'), this.make_purchase_return);
 			}
 		}
-		
+
 		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
 	},
 
@@ -111,7 +110,7 @@
 			frm: cur_frm
 		})
 	},
-	
+
 	make_purchase_return: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_return",