Merge branch 'v4.x.x'
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 31f0e77..44a6b21 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
 from __future__ import unicode_literals
-__version__ = '4.24.4'
+__version__ = '4.25.0'
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 8b23115..9d1769b 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -464,7 +464,7 @@
 
 	def make_gl_entries(self, repost_future_gle=True):
 		gl_entries = self.get_gl_entries()
-
+		
 		if gl_entries:
 			from erpnext.accounts.general_ledger import make_gl_entries
 
@@ -481,6 +481,10 @@
 				and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
 					items, warehouses = self.get_items_and_warehouses()
 					update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
+		elif self.docstatus == 2 and cint(self.update_stock) \
+			and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
+				from erpnext.accounts.general_ledger import delete_gl_entries
+				delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 
 	def get_gl_entries(self, warehouse_account=None):
 		from erpnext.accounts.general_ledger import merge_similar_entries
@@ -509,7 +513,7 @@
 					"debit": self.grand_total,
 					"remarks": self.remarks,
 					"against_voucher": self.name,
-					"against_voucher_type": self.doctype,
+					"against_voucher_type": self.doctype
 				})
 			)
 
@@ -543,6 +547,7 @@
 		# expense account gl entries
 		if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
 				and cint(self.update_stock):
+
 			gl_entries += super(SalesInvoice, self).get_gl_entries()
 
 	def make_pos_gl_entries(self, gl_entries):
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index a546799..0fd41f4 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -135,23 +135,23 @@
 
 	def prepare_conditions(self):
 		conditions = [""]
-		values = {}
+		values = []
 
 		if self.filters.company:
-			conditions.append("company=%(company)s")
-			values["company"] = self.filters.company
+			conditions.append("company=%s")
+			values.append(self.filters.company)
 
 		if self.filters.account:
-			conditions.append("account=%(account)s")
-			values["account"] = self.filters.account
+			conditions.append("account=%s")
+			values.apppend(self.filters.account)
 		else:
 			account_map = self.get_account_map()
 			if not account_map:
 				frappe.throw(_("No Customer Accounts found."))
 			else:
-				accounts_list = ["'{0}'".format(frappe.db.escape(ac)) for ac in account_map]
-				conditions.append("account in ({0})".format(", ".join(accounts_list)))
-
+				conditions.append("account in ({0})".format(", ".join(["%s"] * len(account_map))))
+				values += account_map.keys()
+				
 		return " and ".join(conditions), values
 
 	def get_gl_entries_for(self, account, against_voucher_type, against_voucher):
diff --git a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json
index bd3be60..697cee0 100644
--- a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json
+++ b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json
@@ -5,12 +5,12 @@
  "doctype": "Report", 
  "idx": 1, 
  "is_standard": "Yes", 
- "modified": "2015-03-30 05:38:45.024005", 
+ "modified": "2015-04-14 11:56:02.323769", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Received Items To Be Billed", 
  "owner": "Administrator", 
- "query": "select\n    `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n    `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`qty` - ifnull((select sum(qty) from `tabPurchase Invoice Item` \n\t    where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n            `tabPurchase Invoice Item`.docstatus = 1 and\n\t    `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t    as \"Qty:Float:110\",\n\t(`tabPurchase Receipt Item`.`base_amount` - ifnull((select sum(base_amount) \n             from `tabPurchase Invoice Item` \n             where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n            `tabPurchase Invoice Item`.docstatus = 1 and\n            `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t    as \"Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\",\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n    `tabPurchase Receipt`.docstatus = 1 and\n    `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent and\n    (`tabPurchase Receipt Item`.qty > ifnull((select sum(qty) from `tabPurchase Invoice Item` \n        where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n            `tabPurchase Invoice Item`.docstatus=1 and \n            `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\norder by `tabPurchase Receipt`.`name` desc", 
+ "query": "select\n    `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n    `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`qty` - ifnull((select sum(qty) from `tabPurchase Invoice Item` \n\t    where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n            `tabPurchase Invoice Item`.docstatus = 1 and\n\t    `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t    as \"Qty:Float:110\",\n\t(`tabPurchase Receipt Item`.`base_amount` - ifnull((select sum(base_amount) \n             from `tabPurchase Invoice Item` \n             where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n            `tabPurchase Invoice Item`.docstatus = 1 and\n            `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t    as \"Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\"\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n    `tabPurchase Receipt`.docstatus = 1 and\n    `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent and\n    (`tabPurchase Receipt Item`.qty > ifnull((select sum(qty) from `tabPurchase Invoice Item` \n        where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n            `tabPurchase Invoice Item`.docstatus=1 and \n            `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\norder by `tabPurchase Receipt`.`name` desc", 
  "ref_doctype": "Purchase Invoice", 
  "report_name": "Received Items To Be Billed", 
  "report_type": "Query Report"
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 09f303f..6a06d24 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -198,6 +198,17 @@
 	def on_update(self):
 		pass
 
+	def before_recurring(self):
+		super(PurchaseOrder, self).before_recurring()
+		
+		for field in ("per_received", "per_billed"):
+			self.set(field, None)
+
+		for d in self.get("po_details"):
+			for field in ("received_qty", "billed_amt", "prevdoc_doctype", "prevdoc_docname", 
+				"prevdoc_detail_docname", "supplier_quotation", "supplier_quotation_item"):
+					d.set(field, None)
+
 def set_missing_values(source, target):
 	target.ignore_pricing_rule = 1
 	target.run_method("set_missing_values")
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 8017423..0896777 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -5,7 +5,7 @@
 app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
 app_icon = "icon-th"
 app_color = "#e74c3c"
-app_version = "4.24.4"
+app_version = "4.25.0"
 
 error_report_email = "support@erpnext.com"
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index e3437a5..60df4ce 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -95,4 +95,6 @@
 erpnext.patches.v4_2.set_item_has_batch
 erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle
 erpnext.patches.v4_2.repost_reserved_qty
-erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
\ No newline at end of file
+erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
+erpnext.patches.v4_2.fix_recurring_orders
+erpnext.patches.v4_2.delete_gl_entries_for_cancelled_invoices
diff --git a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
new file mode 100644
index 0000000..0e7796a
--- /dev/null
+++ b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice` 
+		where docstatus = 2 and ifnull(update_stock, 0) = 1""")
+
+	frappe.db.sql("""delete from `tabGL Entry` 
+		where voucher_type = 'Sales Invoice' and voucher_no in (%s)""" 
+		% (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/fix_recurring_orders.py b/erpnext/patches/v4_2/fix_recurring_orders.py
new file mode 100644
index 0000000..ea1724a
--- /dev/null
+++ b/erpnext/patches/v4_2/fix_recurring_orders.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	sales_orders = frappe.db.sql("""select name from `tabSales Order` 
+		where docstatus = 1 and ifnull(is_recurring, 0) = 1 
+		and (per_delivered > 0 or per_billed > 0)""", as_dict=1)
+
+	for so in sales_orders:
+		if not frappe.db.exists("Delivery Note Item", {"against_sales_order": so.name, "docstatus": 1}):
+			frappe.db.sql("""update `tabSales Order` set per_delivered = 0, 
+				delivery_status = 'Not Delivered' where name = %s""", so.name)
+			frappe.db.sql("""update `tabSales Order Item` set delivered_qty = 0
+				where parent = %s""", so.name)
+
+		if not frappe.db.exists("Sales Invoice Item", {"sales_order": so.name, "docstatus": 1}):
+			frappe.db.sql("""update `tabSales Order` set per_billed = 0, 
+				billing_status = 'Not Billed' where name = %s""", so.name)
+			frappe.db.sql("""update `tabSales Order Item` set billed_amt = 0
+				where parent = %s""", so.name)
+
+	purchase_orders = frappe.db.sql("""select name from `tabPurchase Order` 
+		where docstatus = 1 and ifnull(is_recurring, 0) = 1 
+		and (per_received > 0 or per_billed > 0)""", as_dict=1)
+
+	for po in purchase_orders:
+		if not frappe.db.exists("Purchase Receipt Item", {"prevdoc_doctype": "Purchase Order", 
+			"prevdoc_docname": po.name, "docstatus": 1}):
+				frappe.db.sql("""update `tabPurchase Order` set per_received = 0
+					where name = %s""", po.name)
+				frappe.db.sql("""update `tabPurchase Order Item` set received_qty = 0
+					where parent = %s""", po.name)
+
+		if not frappe.db.exists("Purchase Invoice Item", {"purchase_order": po.name, "docstatus": 1}):
+			frappe.db.sql("""update `tabPurchase Order` set per_billed = 0
+				where name = %s""", po.name)
+			frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0
+				where parent = %s""", po.name)
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 5b0f7e9..040b999 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -249,6 +249,17 @@
 	def get_portal_page(self):
 		return "order" if self.docstatus==1 else None
 
+	def before_recurring(self):
+		super(SalesOrder, self).before_recurring()
+		
+		for field in ("delivery_status", "per_delivered", "billing_status", "per_billed"):
+			self.set(field, None)
+
+		for d in self.get("sales_order_details"):
+			for field in ("delivered_qty", "billed_amt", "planned_qty", "prevdoc_docname"):
+				d.set(field, None)
+			
+
 @frappe.whitelist()
 def make_material_request(source_name, target_doc=None):
 	def postprocess(source, doc):
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 117232d..585872e 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -17,7 +17,6 @@
 	onload: function() {
 		this._super();
 		this.setup_queries();
-		this.toggle_editable_price_list_rate();
 	},
 
 	onload_post_render: function() {
@@ -104,6 +103,7 @@
 			var packing_list_exists = (this.frm.doc.packing_details || []).length;
 			this.frm.toggle_display("packing_list", packing_list_exists ? true : false);
 		}
+		this.toggle_editable_price_list_rate();
 	},
 
 	customer: function() {
diff --git a/setup.py b/setup.py
index 4efe4d2..ecb2e6e 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
 from setuptools import setup, find_packages
 import os
 
-version = "4.24.4"
+version = "4.25.0"
 
 with open("requirements.txt", "r") as f:
 	install_requires = f.readlines()