[fix] obey no_copy while creating recurring documents
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 92fee00..da28767 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1563,7 +1563,7 @@
    "in_list_view": 0, 
    "label": "Write Off Account", 
    "length": 0, 
-   "no_copy": 1, 
+   "no_copy": 0, 
    "options": "Account", 
    "permlevel": 0, 
    "print_hide": 1, 
@@ -1588,7 +1588,7 @@
    "in_list_view": 0, 
    "label": "Write Off Cost Center", 
    "length": 0, 
-   "no_copy": 1, 
+   "no_copy": 0, 
    "options": "Cost Center", 
    "permlevel": 0, 
    "print_hide": 1, 
@@ -2487,7 +2487,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2015-12-17 16:18:58.177334", 
+ "modified": "2016-01-25 05:18:57.728258", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice", 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 5d91426..6d61abe 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -263,9 +263,9 @@
 		# parent's gl entry
 		if self.grand_total:
 			# Didnot use base_grand_total to book rounding loss gle
-			grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate, 
+			grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
 				self.precision("grand_total"))
-			
+
 			gl_entries.append(
 				self.get_gl_dict({
 					"account": self.credit_to,
@@ -454,6 +454,9 @@
 		for pr in set(updated_pr):
 			frappe.get_doc("Purchase Receipt", pr).update_billing_percentage(update_modified=update_modified)
 
+	def on_recurring(self, reference_doc):
+		self.due_date = None
+
 @frappe.whitelist()
 def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index e87794a..3c60bfb 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -532,9 +532,9 @@
 	def make_customer_gl_entry(self, gl_entries):
 		if self.grand_total:
 			# Didnot use base_grand_total to book rounding loss gle
-			grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate, 
+			grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
 				self.precision("grand_total"))
-				
+
 			gl_entries.append(
 				self.get_gl_dict({
 					"account": self.debit_to,
@@ -656,6 +656,12 @@
 		for dn in set(updated_delivery_notes):
 			frappe.get_doc("Delivery Note", dn).update_billing_percentage(update_modified=update_modified)
 
+	def on_recurring(self, reference_doc):
+		for fieldname in ("c_form_applicable", "c_form_no", "write_off_amount"):
+			self.set(fieldname, reference_doc.get(fieldname))
+
+		self.due_date = None
+
 def get_list_context(context=None):
 	from erpnext.controllers.website_list_for_contact import get_list_context
 	list_context = get_list_context(context)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index f68935f..caefe53 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -84,11 +84,11 @@
 			if d.prevdoc_detail_docname and not d.schedule_date:
 				d.schedule_date = frappe.db.get_value("Material Request Item",
 						d.prevdoc_detail_docname, "schedule_date")
-						
+
 
 	def get_last_purchase_rate(self):
 		"""get last purchase rates for all items"""
-		
+
 		conversion_rate = flt(self.get('conversion_rate')) or 1.0
 
 		for d in self.get("items"):
@@ -96,7 +96,7 @@
 				last_purchase_details = get_last_purchase_details(d.item_code, self.name)
 
 				if last_purchase_details:
-					d.base_price_list_rate = (last_purchase_details['base_price_list_rate'] * 
+					d.base_price_list_rate = (last_purchase_details['base_price_list_rate'] *
 						(flt(d.conversion_factor) or 1.0))
 					d.discount_percentage = last_purchase_details['discount_percentage']
 					d.base_rate = last_purchase_details['base_rate'] * (flt(d.conversion_factor) or 1.0)
@@ -104,7 +104,7 @@
 					d.rate = d.base_rate / conversion_rate
 				else:
 					# if no last purchase found, reset all values to 0
-					for field in ("base_price_list_rate", "base_rate", 
+					for field in ("base_price_list_rate", "base_rate",
 						"price_list_rate", "rate", "discount_percentage"):
 							d.set(field, 0)
 
@@ -188,7 +188,7 @@
 	def on_cancel(self):
 		if self.is_against_so():
 			self.update_status_updater()
-			
+
 		if self.has_drop_ship_item():
 			self.update_delivered_qty_in_sales_order()
 
@@ -219,17 +219,6 @@
 	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("items"):
-			for field in ("received_qty", "billed_amt", "prevdoc_doctype", "prevdoc_docname",
-				"prevdoc_detail_docname", "supplier_quotation", "supplier_quotation_item"):
-					d.set(field, None)
-
 	def update_status_updater(self):
 		self.status_updater[0].update({
 			"target_parent_dt": "Sales Order",
@@ -254,7 +243,7 @@
 
 	def has_drop_ship_item(self):
 		return any([d.delivered_by_supplier for d in self.items])
-		
+
 	def is_against_so(self):
 		return any([d.prevdoc_doctype for d in self.items if d.prevdoc_doctype=="Sales Order"])
 
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 1988a6d..94dd070 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -19,16 +19,16 @@
 
 	def test_ordered_qty(self):
 		existing_ordered_qty = get_ordered_qty()
-		
+
 		po = create_purchase_order(do_not_submit=True)
 		self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name)
-		
+
 		po.submit()
 		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 10)
 
-		create_pr_against_po(po.name)	
+		create_pr_against_po(po.name)
 		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 6)
-		
+
 		po.load_from_db()
 		self.assertEquals(po.get("items")[0].received_qty, 4)
 
@@ -36,13 +36,13 @@
 
 		pr = create_pr_against_po(po.name, received_qty=8)
 		self.assertEqual(get_ordered_qty(), existing_ordered_qty)
-		
+
 		po.load_from_db()
 		self.assertEquals(po.get("items")[0].received_qty, 12)
 
 		pr.cancel()
 		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 6)
-		
+
 		po.load_from_db()
 		self.assertEquals(po.get("items")[0].received_qty, 4)
 
@@ -70,19 +70,19 @@
 		from erpnext.utilities.transaction_base import UOMMustBeIntegerError
 		po = create_purchase_order(qty=3.4, do_not_save=True)
 		self.assertRaises(UOMMustBeIntegerError, po.insert)
-	
-	def test_ordered_qty_for_closing_po(self):			
-		bin = frappe.get_all("Bin", filters={"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, 
-			fields=["ordered_qty"])	
-		
+
+	def test_ordered_qty_for_closing_po(self):
+		bin = frappe.get_all("Bin", filters={"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"},
+			fields=["ordered_qty"])
+
 		existing_ordered_qty = bin[0].ordered_qty if bin else 0.0
-			
+
 		po = create_purchase_order(item_code= "_Test Item", qty=1)
-		
+
 		self.assertEquals(get_ordered_qty(item_code= "_Test Item", warehouse="_Test Warehouse - _TC"), existing_ordered_qty+1)
-		
+
 		po.update_status("Closed")
-		
+
 		self.assertEquals(get_ordered_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"), existing_ordered_qty)
 
 def create_purchase_order(**args):
@@ -108,9 +108,9 @@
 		po.insert()
 		if not args.do_not_submit:
 			po.submit()
-			
+
 	return po
-	
+
 def create_pr_against_po(po, received_qty=4):
 	pr = make_purchase_receipt(po)
 	pr.get("items")[0].qty = received_qty
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 0d08796..84afbe0 100755
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -7,6 +7,7 @@
  "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
+ "document_type": "Document", 
  "fields": [
   {
    "allow_on_submit": 0, 
@@ -1155,7 +1156,7 @@
    "in_list_view": 0, 
    "label": "BOM", 
    "length": 0, 
-   "no_copy": 1, 
+   "no_copy": 0, 
    "options": "BOM", 
    "permlevel": 0, 
    "precision": "", 
@@ -1330,7 +1331,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2016-01-06 02:21:10.407871", 
+ "modified": "2016-01-25 05:39:52.405200", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Order Item", 
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 5c84112..9aab8eb 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -60,12 +60,6 @@
 			validate_recurring_document(self)
 			convert_to_recurring(self, self.get("posting_date") or self.get("transaction_date"))
 
-	def before_recurring(self):
-		if self.meta.get_field("fiscal_year"):
-			self.fiscal_year = None
-		if self.meta.get_field("due_date"):
-			self.due_date = None
-
 	def set_missing_values(self, for_validate=False):
 		for fieldname in ["posting_date", "transaction_date"]:
 			if not self.get(fieldname) and self.meta.get_field(fieldname):
diff --git a/erpnext/controllers/recurring_document.py b/erpnext/controllers/recurring_document.py
index d34002b..013a70e 100644
--- a/erpnext/controllers/recurring_document.py
+++ b/erpnext/controllers/recurring_document.py
@@ -47,12 +47,9 @@
 				where %s=%s and recurring_id=%s and docstatus=1"""
 				% (doctype, date_field, '%s', '%s'), (next_date, recurring_id)):
 			try:
-				ref_wrapper = frappe.get_doc(doctype, ref_document)
-				if hasattr(ref_wrapper, "before_recurring"):
-					ref_wrapper.before_recurring()
-
-				new_document_wrapper = make_new_document(ref_wrapper, date_field, next_date)
-				send_notification(new_document_wrapper)
+				reference_doc = frappe.get_doc(doctype, ref_document)
+				new_doc = make_new_document(reference_doc, date_field, next_date)
+				send_notification(new_doc)
 				if commit:
 					frappe.db.commit()
 			except:
@@ -63,8 +60,8 @@
 					frappe.db.sql("update `tab%s` \
 						set is_recurring = 0 where name = %s" % (doctype, '%s'),
 						(ref_document))
-					notify_errors(ref_document, doctype, ref_wrapper.get("customer") or ref_wrapper.get("supplier"),
-						ref_wrapper.owner)
+					notify_errors(ref_document, doctype, reference_doc.get("customer") or reference_doc.get("supplier"),
+						reference_doc.owner)
 					frappe.db.commit()
 
 				exception_list.append(frappe.get_traceback())
@@ -76,34 +73,42 @@
 		exception_message = "\n\n".join([cstr(d) for d in exception_list])
 		frappe.throw(exception_message)
 
-def make_new_document(ref_wrapper, date_field, posting_date):
+def make_new_document(reference_doc, date_field, posting_date):
 	from erpnext.accounts.utils import get_fiscal_year
-	new_document = frappe.copy_doc(ref_wrapper)
-	mcount = month_map[ref_wrapper.recurring_type]
+	new_document = frappe.copy_doc(reference_doc, ignore_no_copy=True)
+	mcount = month_map[reference_doc.recurring_type]
 
-	from_date = get_next_date(ref_wrapper.from_date, mcount)
+	from_date = get_next_date(reference_doc.from_date, mcount)
 
 	# get last day of the month to maintain period if the from date is first day of its own month
 	# and to date is the last day of its own month
-	if (cstr(get_first_day(ref_wrapper.from_date)) == cstr(ref_wrapper.from_date)) and \
-		(cstr(get_last_day(ref_wrapper.to_date)) == cstr(ref_wrapper.to_date)):
-			to_date = get_last_day(get_next_date(ref_wrapper.to_date, mcount))
+	if (cstr(get_first_day(reference_doc.from_date)) == cstr(reference_doc.from_date)) and \
+		(cstr(get_last_day(reference_doc.to_date)) == cstr(reference_doc.to_date)):
+			to_date = get_last_day(get_next_date(reference_doc.to_date, mcount))
 	else:
-		to_date = get_next_date(ref_wrapper.to_date, mcount)
+		to_date = get_next_date(reference_doc.to_date, mcount)
 
 	new_document.update({
 		date_field: posting_date,
 		"from_date": from_date,
 		"to_date": to_date,
-		"fiscal_year": get_fiscal_year(posting_date)[0],
-		"owner": ref_wrapper.owner,
+		"fiscal_year": get_fiscal_year(posting_date)[0]
 	})
 
-	if ref_wrapper.doctype == "Sales Order":
-		new_document.update({
-			"delivery_date": get_next_date(ref_wrapper.delivery_date, mcount,
-				cint(ref_wrapper.repeat_on_day_of_month))
-	})
+	# copy document fields
+	for fieldname in ("owner", "recurring_type", "repeat_on_day_of_month",
+		"recurring_id", "notification_email_address", "is_recurring", "end_date",
+		"title", "naming_series", "select_print_heading", "ignore_pricing_rule",
+		"posting_time", "remarks"):
+		if new_document.meta.get_field(fieldname):
+			new_document.set(fieldname, reference_doc.get(fieldname))
+
+	# copy item fields
+	for i, item in enumerate(new_document.items):
+		for fieldname in ("page_break",):
+			item.set(fieldname, reference_doc.items[i].get(fieldname))
+
+	new_document.run_method("on_recurring", reference_doc=reference_doc)
 
 	new_document.submit()
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 8bc96e6..aafb0df 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -10,6 +10,7 @@
 from frappe.model.mapper import get_mapped_doc
 from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
 from frappe.desk.notifications import clear_doctype_notifications
+from erpnext.controllers.recurring_document import month_map, get_next_date
 
 from erpnext.controllers.selling_controller import SellingController
 
@@ -288,13 +289,13 @@
 
 		frappe.db.set_value("Sales Order", self.name, "per_delivered", flt(delivered_qty/tot_qty) * 100,
 		update_modified=False)
-	
+
 	def set_indicator(self):
 		"""Set indicator for portal"""
 		if self.per_billed < 100 and self.per_delivered < 100:
 			self.indicator_color = "orange"
 			self.indicator_title = _("Not Paid and Not Delivered")
-		
+
 		elif self.per_billed == 100 and self.per_delivered < 100:
 			self.indicator_color = "orange"
 			self.indicator_title = _("Paid and Not Delivered")
@@ -302,7 +303,12 @@
 		else:
 			self.indicator_color = "green"
 			self.indicator_title = _("Paid")
-			
+
+	def on_recurring(self, reference_doc):
+		mcount = month_map[reference_doc.recurring_type]
+		self.set("delivery_date", get_next_date(reference_doc.delivery_date, mcount,
+						cint(reference_doc.repeat_on_day_of_month)))
+
 def get_list_context(context=None):
 	from erpnext.controllers.website_list_for_contact import get_list_context
 	list_context = get_list_context(context)
@@ -328,17 +334,6 @@
 
 	frappe.local.message_log = []
 
-	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("items"):
-			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):