refactor: refactor contextual print setting implementation
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py
index 56576df..50ec7d8 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py
@@ -6,8 +6,5 @@
 
 from frappe.model.document import Document
 
-from erpnext.controllers.print_settings import print_settings_for_item_table
-
 class PurchaseInvoiceItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py
index 7a62f8e..a73b03a 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py
@@ -5,8 +5,6 @@
 import frappe
 
 from frappe.model.document import Document
-from erpnext.controllers.print_settings import print_settings_for_item_table
 
 class SalesInvoiceItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
index 1d758e8..3d5a9b1 100644
--- a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
+++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
@@ -1,5 +1,5 @@
 {%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value, fieldmeta,
-	get_width, get_align_class -%}
+	get_width, get_align_class with context -%}
 
 {%- macro render_currency(df, doc) -%}
 <div class="row {% if df.bold %}important{% endif %} data-field">
@@ -63,14 +63,19 @@
 					<tr>
 						<td class="table-sr">{{ d.idx }}</td>
 						{% for tdf in visible_columns %}
-						{% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+						{% if not print_settings.compact_item_print or tdf.fieldname in doc.flags.compact_item_fields %}
 							<td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
 								{% if tdf.fieldname == 'qty' %}
 									<div class="value">{{ (d[tdf.fieldname])|abs }}</div></td>
 								{% elif tdf.fieldtype == 'Currency' %}
 									<div class="value">{{ frappe.utils.fmt_money((d[tdf.fieldname])|abs, currency=doc.currency) }}</div></td>
 								{% else %}
-									<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
+									{% if doc.child_print_templates %}
+										{%- set child_templates = doc.child_print_templates.get(df.fieldname) -%}
+											<div class="value">{{ print_value(tdf, d, doc, visible_columns, child_templates) }}</div></td>
+										{% else %}
+											<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
+									{% endif %}
 								{% endif %}
 						{% endif %}
 						{% endfor %}
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py
index b711e36..8bdcd47 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py
@@ -6,11 +6,8 @@
 
 from frappe.model.document import Document
 
-from erpnext.controllers.print_settings import print_settings_for_item_table
-
 class PurchaseOrderItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
 
 def on_doctype_update():
 	frappe.db.add_index("Purchase Order Item", ["item_code", "warehouse"])
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py
index f24e5be..64dda87 100644
--- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py
+++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py
@@ -6,8 +6,5 @@
 
 from frappe.model.document import Document
 
-from erpnext.controllers.print_settings import print_settings_for_item_table
-
 class SupplierQuotationItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 1665649..c016090 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -22,6 +22,7 @@
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 from erpnext.stock.get_item_details import get_item_warehouse, _get_item_tax_template, get_item_tax_map
 from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
+from erpnext.controllers.print_settings import set_print_templates_for_item_table, set_print_templates_for_taxes
 
 force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
 
@@ -29,6 +30,19 @@
 	def __init__(self, *args, **kwargs):
 		super(AccountsController, self).__init__(*args, **kwargs)
 
+	def get_print_settings(self):
+		print_setting_fields = []
+		items_field = self.meta.get_field('items')
+
+		if items_field and items_field.fieldtype == 'Table':
+			print_setting_fields += ['compact_item_print', 'print_uom_after_quantity']
+
+		taxes_field = self.meta.get_field('taxes')
+		if taxes_field and taxes_field.fieldtype == 'Table':
+			print_setting_fields += ['print_taxes_with_zero_amount']
+
+		return print_setting_fields
+
 	@property
 	def company_currency(self):
 		if not hasattr(self, "__company_currency"):
@@ -138,7 +152,7 @@
 		elif self.doctype in ("Quotation", "Purchase Order", "Sales Order"):
 			self.validate_non_invoice_documents_schedule()
 
-	def before_print(self):
+	def before_print(self, settings=None):
 		if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice',
 							'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']:
 			if self.get("group_same_items"):
@@ -151,6 +165,9 @@
 			else:
 				df.set("print_hide", 1)
 
+		set_print_templates_for_item_table(self, settings)
+		set_print_templates_for_taxes(self, settings)
+
 	def calculate_paid_amount(self):
 		if hasattr(self, "is_pos") or hasattr(self, "is_paid"):
 			is_paid = self.get("is_pos") or self.get("is_paid")
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 596f6f4..353bc09 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -13,23 +13,11 @@
 from erpnext.stock.doctype.stock_entry.stock_entry import get_used_alternative_items
 from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos
 from frappe.contacts.doctype.address.address import get_address_display
-from erpnext.controllers.print_settings import print_settings_for_taxes
 
 from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
 from erpnext.controllers.stock_controller import StockController
 
 class BuyingController(StockController):
-	def __setup__(self):
-		if hasattr(self, "taxes"):
-			print_settings_for_taxes(self)
-
-	def before_print(self):
-		pass
-
-	def get_print_settings(self):
-		items_field = self.meta.get_field('items')
-		if items_field and items_field.fieldtype == 'Table':
-			return ['compact_item_print', 'print_uom_after_quantity']
 
 	def get_feed(self):
 		if self.get("supplier_name"):
diff --git a/erpnext/controllers/print_settings.py b/erpnext/controllers/print_settings.py
index 418d8eb..e08c400 100644
--- a/erpnext/controllers/print_settings.py
+++ b/erpnext/controllers/print_settings.py
@@ -5,41 +5,33 @@
 import frappe
 from frappe.utils import cint
 
-def print_settings_for_item_table(doc, settings=None):
+def set_print_templates_for_item_table(doc, settings):
 	doc.print_templates = {
-		"qty": "templates/print_formats/includes/item_table_qty.html"
+		"items": "templates/print_formats/includes/items.html",
 	}
-	doc.hide_in_print_layout = ["uom", "stock_uom"]
 
-	setting_fields = ['compact_item_print', 'print_uom_after_quantity']
-	set_doc_flags_from_settings(doc, setting_fields, settings)
+	doc.child_print_templates = {
+		"items": {
+			"qty": "templates/print_formats/includes/item_table_qty.html",
+		}
+	}
 
-	if doc.flags.compact_item_print:
-		doc.print_templates["description"] = "templates/print_formats/includes/item_table_description.html"
-		doc.flags.compact_item_fields = ["description", "qty", "rate", "amount"]
+	if doc.meta.get_field("items"):
+		doc.meta.get_field("items").hide_in_print_layout = ["uom", "stock_uom"]
+
+	doc.flags.compact_item_fields = ["description", "qty", "rate", "amount"]
+
+	if settings.compact_item_print:
+		doc.child_print_templates["items"]["description"] =\
+			"templates/print_formats/includes/item_table_description.html"
 		doc.flags.format_columns = format_columns
 
-def print_settings_for_taxes(doc, settings=None):
-
-	set_doc_flags_from_settings(doc, ['print_taxes_with_zero_amount'], settings)
-
+def set_print_templates_for_taxes(doc, settings):
 	doc.flags.show_inclusive_tax_in_print = doc.is_inclusive_tax()
-
-	doc.print_templates = {
+	doc.print_templates.update({
 		"total": "templates/print_formats/includes/total.html",
 		"taxes": "templates/print_formats/includes/taxes.html"
-	}
-
-def set_doc_flags_from_settings(doc, fields, settings=None):
-	if not settings: settings = {}
-
-	print_settings = frappe.get_single('Print Settings')
-
-	for field in fields:
-		if field in settings:
-			doc.flags[field] = settings.get(field)
-		else:
-			doc.flags[field] = print_settings.get(field)
+	})
 
 def format_columns(display_columns, compact_fields):
 	compact_fields = compact_fields + ["image", "item_code", "item_name"]
@@ -48,39 +40,3 @@
 		if column not in compact_fields:
 			final_columns.append(column)
 	return final_columns
-
-def has_items_field(doc):
-	meta = frappe.get_meta(doc.doctype)
-	items_field = meta.get_field('items')
-	if items_field and items_field.fieldtype == 'Table':
-		return True
-	return False
-
-def has_taxes_field(doc):
-	meta = frappe.get_meta(doc.doctype)
-	taxes_field = meta.get_field('taxes')
-	if taxes_field and taxes_field.fieldtype == 'Table':
-		return True
-	return False
-
-def get_print_settings():
-
-	# return ['comp']
-	settings = {
-		'compact_item_print': {
-			'condition': 'erpnext.controllers.print_settings.has_items_field',
-			'child_field': 'items',
-			# 'set_template': 'erpnext.controllers.print_settings.print_settings_for_item_table'
-		},
-		'print_uom_after_quantity': {
-			'condition': 'erpnext.controllers.print_settings.has_taxes_field',
-			'child_field': 'items',
-			# 'set_template': 'erpnext.controllers.print_settings.print_settings_for_item_table'
-		},
-		'print_taxes_with_zero_amount': {
-			'condition': 'erpnext.controllers.print_settings.has_taxes_field',
-			# 'set_template': 'erpnext.controllers.print_settings.print_settings_for_taxes'
-		}
-	}
-
-	return settings
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 4c87e8c..de3cda5 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -11,26 +11,10 @@
 from erpnext.stock.doctype.item.item import set_item_default
 from frappe.contacts.doctype.address.address import get_address_display
 from erpnext.controllers.accounts_controller import get_taxes_and_charges
-from erpnext.controllers.print_settings import print_settings_for_taxes
 
 from erpnext.controllers.stock_controller import StockController
 
 class SellingController(StockController):
-	def __setup__(self):
-		if hasattr(self, "taxes"):
-			print_settings_for_taxes(self)
-
-	def before_print(self):
-		self.print_templates = {
-			"items": "templates/print_formats/includes/items.html",
-		}
-		self.flags.compact_item_fields = ['description']
-
-	def get_print_settings(self):
-		items_field = self.meta.get_field('items')
-		if items_field and items_field.fieldtype == 'Table':
-			return ['compact_item_print', 'print_uom_after_quantity']
-
 
 	def get_feed(self):
 		return _("To {0} | {1} {2}").format(self.customer_name, self.currency,
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 5bbd29c..24d0dc1 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -26,7 +26,7 @@
 
 		self.update_costing()
 
-	def before_print(self):
+	def before_print(self, settings=None):
 		self.onload()
 
 
diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.py b/erpnext/selling/doctype/quotation_item/quotation_item.py
index 966b542..7384871 100644
--- a/erpnext/selling/doctype/quotation_item/quotation_item.py
+++ b/erpnext/selling/doctype/quotation_item/quotation_item.py
@@ -5,8 +5,6 @@
 import frappe
 
 from frappe.model.document import Document
-from erpnext.controllers.print_settings import print_settings_for_item_table
 
 class QuotationItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.py b/erpnext/selling/doctype/sales_order_item/sales_order_item.py
index 4a87a0c..27f303d 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.py
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.py
@@ -5,11 +5,9 @@
 import frappe
 
 from frappe.model.document import Document
-from erpnext.controllers.print_settings import print_settings_for_item_table
 
 class SalesOrderItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
 
 def on_doctype_update():
 	frappe.db.add_index("Sales Order Item", ["item_code", "warehouse"])
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index d04cf78..1994dfd 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -71,7 +71,7 @@
 					where name=`tabSales Invoice Item`.parent and is_return=1 and update_stock=1)"""
 			})
 
-	def before_print(self):
+	def before_print(self, settings=None):
 		def toggle_print_hide(meta, fieldname):
 			df = meta.get_field(fieldname)
 			if self.get("print_without_amount"):
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py
index aaca802..5030595 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py
@@ -5,8 +5,6 @@
 import frappe
 
 from frappe.model.document import Document
-from erpnext.controllers.print_settings import print_settings_for_item_table
 
 class DeliveryNoteItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.py b/erpnext/stock/doctype/material_request_item/material_request_item.py
index 6c6ecfe..16f007f 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.py
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.py
@@ -6,12 +6,10 @@
 from __future__ import unicode_literals
 import frappe
 
-from erpnext.controllers.print_settings import print_settings_for_item_table
 from frappe.model.document import Document
 
 class MaterialRequestItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
 
 def on_doctype_update():
 	frappe.db.add_index("Material Request Item", ["item_code", "warehouse"])
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py
index 679bd1e..b79bb5d 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py
@@ -5,8 +5,6 @@
 import frappe
 
 from frappe.model.document import Document
-from erpnext.controllers.print_settings import print_settings_for_item_table
 
 class PurchaseReceiptItem(Document):
-	def __setup__(self):
-		print_settings_for_item_table(self)
+	pass
diff --git a/erpnext/templates/print_formats/includes/item_table_description.html b/erpnext/templates/print_formats/includes/item_table_description.html
index 070cca5..ed46c9e 100644
--- a/erpnext/templates/print_formats/includes/item_table_description.html
+++ b/erpnext/templates/print_formats/includes/item_table_description.html
@@ -1,7 +1,7 @@
-{%- set compact = doc.flags.compact_item_print -%}
-{%- set compact_fields = doc.flags.compact_item_fields -%}
+{%- set compact = print_settings.compact_item_print -%}
+{%- set compact_fields = parent_doc.flags.compact_item_fields -%}
 {%- set display_columns = visible_columns|map(attribute="fieldname")| list -%}
-{%- set columns = doc.flags.format_columns(display_columns, compact_fields) -%}
+{%- set columns = parent_doc.flags.format_columns(display_columns, compact_fields) -%}
 
 {% if doc.in_format_data("image") and doc.get("image") and "image" in display_columns -%}
 <div class="pull-left" style="max-width: 40%; margin-right: 10px;">
diff --git a/erpnext/templates/print_formats/includes/item_table_qty.html b/erpnext/templates/print_formats/includes/item_table_qty.html
index 1d992dc..8e68f1c 100644
--- a/erpnext/templates/print_formats/includes/item_table_qty.html
+++ b/erpnext/templates/print_formats/includes/item_table_qty.html
@@ -1,4 +1,4 @@
-{% set qty_first=doc.flags.print_uom_after_quantity %}
+{% set qty_first=print_settings.print_uom_after_quantity %}
 {% if qty_first %}
 	{{ doc.get_formatted("qty", doc) }}
 	{% if (doc.uom and not doc.is_print_hide("uom")) %} {{ _(doc.uom) }}
diff --git a/erpnext/templates/print_formats/includes/items.html b/erpnext/templates/print_formats/includes/items.html
index 933ae17..55598e7 100644
--- a/erpnext/templates/print_formats/includes/items.html
+++ b/erpnext/templates/print_formats/includes/items.html
@@ -1,14 +1,13 @@
 {%- if data -%}
 	{%- set visible_columns = get_visible_columns(doc.get(df.fieldname),
 		table_meta, df) -%}
-
 	<div {{ fieldmeta(df) }}>
 		<table class="table table-bordered table-condensed">
 			<thead>
 				<tr>
 					<th style="width: 40px" class="table-sr">{{ _("Sr") }}</th>
 					{% for tdf in visible_columns %}
-					{% if (data and not print_settings.compact_item_print) or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+					{% if (data and not print_settings.compact_item_print) or tdf.fieldname in doc.flags.compact_item_fields %}
 						<th style="width: {{ get_width(tdf) }};" class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
 							{{ _(tdf.label) }}</th>
 					{% endif %}
@@ -20,9 +19,14 @@
 				<tr>
 					<td class="table-sr">{{ d.idx }}</td>
 					{% for tdf in visible_columns %}
-					{% if not doc.get(df.fieldname)[0].flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+					{% if not print_settings.compact_item_print or tdf.fieldname in doc.flags.compact_item_fields %}
 						<td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
-						<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
+						{% if doc.child_print_templates %}
+							{%- set child_templates = doc.child_print_templates.get(df.fieldname) %}
+							<div class="value">{{ print_value(tdf, d, doc, visible_columns, child_templates) }}</div></td>
+						{% else %}
+							<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
+						{% endif %}
 					{% endif %}
 					{% endfor %}
 				</tr>
diff --git a/erpnext/templates/print_formats/includes/taxes.html b/erpnext/templates/print_formats/includes/taxes.html
index 6e984f3..334ac78 100644
--- a/erpnext/templates/print_formats/includes/taxes.html
+++ b/erpnext/templates/print_formats/includes/taxes.html
@@ -17,7 +17,7 @@
 			{{ render_discount_amount(doc) }}
 		{%- endif -%}
 		{%- for charge in data -%}
-			{%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
+			{%- if (charge.tax_amount or print_settings.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
 			<div class="row">
 				<div class="col-xs-5 {%- if doc.align_labels_right %} text-right{%- endif -%}">
 					<label>{{ charge.get_formatted("description") }}</label></div>