Merge branch 'develop'
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 64f6e28..0d53216 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1 +1 @@
-__version__ = '4.7.2'
+__version__ = '4.8.0'
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index dab2d82..4cc3d57 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -124,6 +124,10 @@
 			from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s
 			and account = %s and ifnull(against_voucher, '') = ''""",
 			(against_voucher, account))[0][0])
+		if not against_voucher_amount:
+			frappe.throw(_("Against Journal Voucher {0} is already adjusted against some other voucher")
+				.format(against_voucher))
+
 		bal = against_voucher_amount + bal
 		if against_voucher_amount < 0:
 			bal = -bal
diff --git a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py
index 3c67508..f9f6df1 100644
--- a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py
+++ b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py
@@ -88,15 +88,24 @@
 	def validate_against_jv(self):
 		for d in self.get('entries'):
 			if d.against_jv:
+				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 entries can be linked against another debit entry")
+						.format(d.account))
+				elif account_root_type == "Liability" and flt(d.credit) > 0:
+					frappe.throw(_("For {0}, only debit entries can be linked against another credit entry")
+						.format(d.account))
+
 				if d.against_jv == self.name:
 					frappe.throw(_("You can not enter current voucher in 'Against Journal Voucher' column"))
 
 				against_entries = frappe.db.sql("""select * from `tabJournal Voucher Detail`
 					where account = %s and docstatus = 1 and parent = %s
-					and ifnull(against_jv, '') = ''""", (d.account, d.against_jv), as_dict=True)
+					and ifnull(against_jv, '') = '' and ifnull(against_invoice, '') = ''
+					and ifnull(against_voucher, '') = ''""", (d.account, d.against_jv), as_dict=True)
 
 				if not against_entries:
-					frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched")
+					frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched against other voucher")
 						.format(d.against_jv, d.account))
 				else:
 					dr_or_cr = "debit" if d.credit > 0 else "credit"
@@ -153,7 +162,7 @@
 					and voucher_account != d.account:
 					frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} account") \
 						.format(d.idx, d.account, doctype, field_dict.get(doctype)))
-					
+
 				if against_field in ["against_sales_order", "against_purchase_order"]:
 					if voucher_account != account_master_name:
 						frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} Name") \
@@ -165,7 +174,7 @@
 
 	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, 
+			voucher_properties = frappe.db.get_value(doctype, voucher_no,
 				["docstatus", "outstanding_amount"])
 
 			if voucher_properties[0] != 1:
@@ -177,7 +186,7 @@
 
 	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, 
+			voucher_properties = frappe.db.get_value(doctype, voucher_no,
 				["docstatus", "per_billed", "status", "advance_paid", "grand_total"])
 
 			if voucher_properties[0] != 1:
@@ -532,9 +541,10 @@
 		(filters["account"], "%%%s%%" % txt, start, page_len))
 
 def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
-	return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
-		from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail
-		where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
+	return frappe.db.sql("""select distinct jv.name, jv.posting_date, jv.user_remark
+		from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jvd
+		where jvd.parent = jv.name and jvd.account = %s and jv.docstatus = 1
+		and (ifnull(jvd.against_invoice, '') = '' and ifnull(jvd.against_voucher, '') = '' and ifnull(jvd.against_jv, '') = '' )
 		and jv.%s like %s order by jv.name desc limit %s, %s""" %
 		("%s", searchfield, "%s", "%s", "%s"),
 		(filters["account"], "%%%s%%" % txt, start, page_len))
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index 97484da..bfcd63e 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -19,9 +19,9 @@
 					]
 				};
 			}
-			
+
 		});
-		
+
 		this.frm.set_query('bank_cash_account', function() {
 			if(!me.frm.doc.company) {
 				msgprint(__("Please select company first"));
@@ -35,12 +35,8 @@
 				};
 			}
 		});
-
-		var help_content = '<i class="icon-hand-right"></i> ' + __("Note") + ':<br>'+
-			'<ul>' + __("If you are unable to match the exact amount, then amend your Journal Voucher and split rows such that payment amount match the invoice amount.") + '</ul>';
-		this.frm.set_value("reconcile_help", help_content);
 	},
-	
+
 	get_unreconciled_entries: function() {
 		var me = this;
 		return this.frm.call({
@@ -48,12 +44,12 @@
 			method: 'get_unreconciled_entries',
 			callback: function(r, rt) {
 				var invoices = [];
-				
+
 				$.each(me.frm.doc.payment_reconciliation_invoices || [], function(i, row) {
-						if (row.invoice_number && !inList(invoices, row.invoice_number)) 
+						if (row.invoice_number && !inList(invoices, row.invoice_number))
 							invoices.push(row.invoice_number);
 				});
-								
+
 				frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
 					me.frm.doc.name).options = invoices.join("\n");
 
@@ -79,4 +75,4 @@
 
 $.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
 
-cur_frm.add_fetch('party_account', 'master_type', 'party_type')
\ No newline at end of file
+cur_frm.add_fetch('party_account', 'master_type', 'party_type')
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
index 51cb306..bb07b46 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
@@ -118,19 +118,12 @@
    "options": "Payment Reconciliation Invoice", 
    "permlevel": 0, 
    "read_only": 1
-  }, 
-  {
-   "fieldname": "reconcile_help", 
-   "fieldtype": "Small Text", 
-   "label": "", 
-   "permlevel": 0, 
-   "read_only": 1
   }
  ], 
  "hide_toolbar": 1, 
  "icon": "icon-resize-horizontal", 
  "issingle": 1, 
- "modified": "2014-07-31 05:43:03.410832", 
+ "modified": "2014-10-16 17:51:44.367107", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Payment Reconciliation", 
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index a5a56ae..c6a2b05 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -124,7 +124,7 @@
 		dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
 		lst = []
 		for e in self.get('payment_reconciliation_payments'):
-			if e.invoice_type and e.invoice_number:
+			if e.invoice_type and e.invoice_number and e.allocated_amount:
 				lst.append({
 					'voucher_no' : e.journal_voucher,
 					'voucher_detail_no' : e.voucher_detail_number,
@@ -134,7 +134,7 @@
 					'is_advance' : e.is_advance,
 					'dr_or_cr' : dr_or_cr,
 					'unadjusted_amt' : flt(e.amount),
-					'allocated_amt' : flt(e.amount)
+					'allocated_amt' : flt(e.allocated_amount)
 				})
 
 		if lst:
@@ -162,18 +162,23 @@
 
 		invoices_to_reconcile = []
 		for p in self.get("payment_reconciliation_payments"):
-			if p.invoice_type and p.invoice_number:
+			if p.invoice_type and p.invoice_number and p.allocated_amount:
 				invoices_to_reconcile.append(p.invoice_number)
 
 				if p.invoice_number not in unreconciled_invoices.get(p.invoice_type, {}):
 					frappe.throw(_("{0}: {1} not found in Invoice Details table")
 						.format(p.invoice_type, p.invoice_number))
 
-				if p.amount > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
-					frappe.throw(_("Row {0}: Payment amount must be less than or equals to invoice outstanding amount. Please refer Note below.").format(p.idx))
+				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))
+
+				if flt(p.allocated_amount) > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
+					frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
+						.format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
 
 		if not invoices_to_reconcile:
-			frappe.throw(_("Please select Invoice Type and Invoice Number in atleast one row"))
+			frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
 
 	def check_condition(self, dr_or_cr):
 		cond = self.from_date and " and posting_date >= '" + self.from_date + "'" or ""
diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
index 73fd0f5..6f576ca 100644
--- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
+++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
@@ -54,10 +54,19 @@
    "permlevel": 0
   }, 
   {
+   "fieldname": "allocated_amount", 
+   "fieldtype": "Currency", 
+   "in_list_view": 1, 
+   "label": "Allocated amount", 
+   "permlevel": 0, 
+   "precision": "", 
+   "reqd": 1
+  }, 
+  {
    "default": "Sales Invoice", 
    "fieldname": "invoice_type", 
    "fieldtype": "Select", 
-   "in_list_view": 1, 
+   "in_list_view": 0, 
    "label": "Invoice Type", 
    "options": "\nSales Invoice\nPurchase Invoice\nJournal Voucher", 
    "permlevel": 0, 
@@ -95,7 +104,7 @@
   }
  ], 
  "istable": 1, 
- "modified": "2014-07-21 16:53:56.206169", 
+ "modified": "2014-10-16 17:40:54.040194", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Payment Reconciliation Payment", 
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index fe989d8..febf4b0 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -4,7 +4,7 @@
 app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
 app_icon = "icon-th"
 app_color = "#e74c3c"
-app_version = "4.7.2"
+app_version = "4.8.0"
 
 error_report_email = "support@erpnext.com"
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 864329d..079b7fc 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -245,7 +245,7 @@
 		sl_entries = []
 		for d in self.get_item_list():
 			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
-					and d.warehouse:
+					and d.warehouse and flt(d['qty']):
 				self.update_reserved_qty(d)
 
 				sl_entries.append(self.get_sl_entries(d, {
diff --git a/erpnext/utilities/repost_stock.py b/erpnext/utilities/repost_stock.py
index 643bec9..f1ba179 100644
--- a/erpnext/utilities/repost_stock.py
+++ b/erpnext/utilities/repost_stock.py
@@ -73,7 +73,7 @@
 					from `tabPacked Item` dnpi_in
 					where item_code = %s and warehouse = %s
 					and parenttype="Sales Order"
-				and item_code != parent_item
+					and item_code != parent_item
 					and exists (select * from `tabSales Order` so
 					where name = dnpi_in.parent and docstatus = 1 and status != 'Stopped')
 				) dnpi)
diff --git a/setup.py b/setup.py
index e567ea2..5c7fe9a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
 from setuptools import setup, find_packages
 import os
 
-version = "4.7.2"
+version = "4.8.0"
 
 with open("requirements.txt", "r") as f:
 	install_requires = f.readlines()
diff --git a/test_sites/test_site/site_config.json b/test_sites/test_site/site_config.json
index 05bf562..12007b8 100644
--- a/test_sites/test_site/site_config.json
+++ b/test_sites/test_site/site_config.json
@@ -1,5 +1,6 @@
 {
  "db_name": "test_frappe",
  "db_password": "test_frappe",
+ "admin_password": "admin",
  "mute_emails": 1
 }