Merge branch 'emakis-in_words_configurable' into develop
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py
index fd88afd..7e05b95 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.py
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py
@@ -19,7 +19,7 @@
 
 	data = []
 	data.extend(asset or [])
-	data.extend(liability or [])
+	data.extend(liability or [])	
 	data.extend(equity or [])
 	if provisional_profit_loss:
 		data.append(provisional_profit_loss)
@@ -43,11 +43,11 @@
 		for period in period_list:
 			effective_liability = 0.0
 			if liability:
-				effective_liability += flt(liability[-2][period.key])
+				effective_liability += flt(liability[-2].get(period.key))
 			if equity:
-				effective_liability += flt(equity[-2][period.key])
+				effective_liability += flt(equity[-2].get(period.key))
 
-			provisional_profit_loss[period.key] = flt(asset[-2][period.key]) - effective_liability
+			provisional_profit_loss[period.key] = flt(asset[-2].get(period.key)) - effective_liability
 
 			if provisional_profit_loss[period.key]:
 				has_value = True
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index d84f18f..0f10b94 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -92,7 +92,7 @@
 	if not accounts:
 		return None
 
-	accounts, accounts_by_name = filter_accounts(accounts)
+	accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
 	
 	company_currency = frappe.db.get_value("Company", company, "default_currency")
 
@@ -109,6 +109,7 @@
 	calculate_values(accounts_by_name, gl_entries_by_account, period_list, accumulated_values)
 	accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values)
 	out = prepare_data(accounts, balance_must_be, period_list, company_currency)
+	out = filter_out_zero_value_rows(out, parent_children_map)
 	
 	if out:
 		add_total_row(out, balance_must_be, period_list, company_currency)
@@ -134,15 +135,15 @@
 					d.get(period.key, 0.0)
 
 def prepare_data(accounts, balance_must_be, period_list, company_currency):
-	out = []
+	data = []
 	year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d")
 	year_end_date = period_list[-1]["year_end_date"].strftime("%Y-%m-%d")
-
+	
 	for d in accounts:
 		# add to output
 		has_value = False
 		total = 0
-		row = {
+		row = frappe._dict({
 			"account_name": d.account_name,
 			"account": d.name,
 			"parent_account": d.parent_account,
@@ -150,7 +151,7 @@
 			"year_start_date": year_start_date,
 			"year_end_date": year_end_date,
 			"currency": company_currency
-		}
+		})
 		for period in period_list:
 			if d.get(period.key):
 				# change sign based on Debit or Credit, since calculation is done using (debit - credit)
@@ -163,11 +164,25 @@
 				has_value = True
 				total += flt(row[period.key])
 
-		if has_value:
-			row["total"] = total
-			out.append(row)
+		row["has_value"] = has_value
+		row["total"] = total
+		data.append(row)
+		
+	return data
+	
+def filter_out_zero_value_rows(data, parent_children_map):
+	data_with_value = []
+	for d in data:
+		if d.get("has_value"):
+			data_with_value.append(d)
+		else:
+			children = [child.name for child in parent_children_map.get(d.account) or []]
+			for row in data:
+				if row.account in children and row.get("has_value"):
+					data_with_value.append(d)
+					break
 
-	return out
+	return data_with_value
 
 def add_total_row(out, balance_must_be, period_list, company_currency):
 	total_row = {
@@ -187,10 +202,11 @@
 			total_row["total"] += flt(row["total"])
 			row["total"] = ""
 	
-	out.append(total_row)
+	if total_row.has_key("total"):
+		out.append(total_row)
 
-	# blank row after Total
-	out.append({})
+		# blank row after Total
+		out.append({})
 
 def get_accounts(company, root_type):
 	return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
@@ -218,7 +234,7 @@
 
 	add_to_list(None, 0)
 
-	return filtered_accounts, accounts_by_name
+	return filtered_accounts, accounts_by_name, parent_children_map
 
 def sort_root_accounts(roots):
 	"""Sort root types as Asset, Liability, Equity, Income, Expense"""
diff --git a/erpnext/controllers/print_settings.py b/erpnext/controllers/print_settings.py
index bc34f7c..5d27b03 100644
--- a/erpnext/controllers/print_settings.py
+++ b/erpnext/controllers/print_settings.py
@@ -8,22 +8,22 @@
 def print_settings_for_item_table(doc):
 
 	doc.print_templates = {
-		"description": "templates/print_formats/includes/item_table_description.html",
 		"qty": "templates/print_formats/includes/item_table_qty.html"
 	}
-
-	doc.hide_in_print_layout = ["item_code", "item_name", "image", "uom", "stock_uom"]
+	doc.hide_in_print_layout = ["uom", "stock_uom"]
 
 	doc.flags.compact_item_print = cint(frappe.db.get_value("Features Setup", None, "compact_item_print"))
-	doc.flags.compact_item_fields = doc.hide_in_print_layout + ["description", "qty", "rate", "amount"]
-	doc.flags.show_in_description = []
 
 	if doc.flags.compact_item_print:
+		doc.print_templates["description"] = "templates/print_formats/includes/item_table_description.html"
+		doc.hide_in_print_layout += ["item_code", "item_name", "image"]
+
+		doc.flags.compact_item_fields = ["description", "qty", "rate", "amount"]
+		doc.flags.show_in_description = []
+
 		for df in doc.meta.fields:
 			if df.fieldtype not in ("Section Break", "Column Break", "Button"):
 				if not doc.is_print_hide(df.fieldname):
 					if df.fieldname not in doc.hide_in_print_layout and df.fieldname not in doc.flags.compact_item_fields:
 						doc.hide_in_print_layout.append(df.fieldname)
 						doc.flags.show_in_description.append(df.fieldname)
-
-
diff --git a/erpnext/docs/user/manual/de/accounts/journal-entry.md b/erpnext/docs/user/manual/de/accounts/journal-entry.md
index f823f0e..0885130 100644
--- a/erpnext/docs/user/manual/de/accounts/journal-entry.md
+++ b/erpnext/docs/user/manual/de/accounts/journal-entry.md
@@ -10,6 +10,7 @@
 <img class="screenshot" alt="Buchungssatz" src="{{docs_base_url}}/assets/img/accounts/journal-entry.png">
 
 In einem Buchungssatz müssen Sie folgendes tun:
+
 * Die Belegart über das DropDown-Menü auswählen.
 * Zeilen für die einzelnen Buchungen hinzufügen. In jeder Zeile müssen Sie folgendes Angeben:
     * Das Konto, das betroffen ist.
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 46ab671..9c5b44d 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -165,6 +165,7 @@
 execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0)
 execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'")
 erpnext.patches.v5_0.update_item_and_description_again
+erpnext.patches.v6_0.multi_currency
 erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
 erpnext.patches.v5_0.portal_fixes
 erpnext.patches.v5_0.reset_values_in_tools
@@ -207,7 +208,6 @@
 execute:frappe.db.sql("""update `tabProject` set percent_complete=round(percent_complete, 2) where percent_complete is not null""")
 erpnext.patches.v6_0.fix_outstanding_amount
 erpnext.patches.v6_0.fix_planned_qty
-erpnext.patches.v6_0.multi_currency
 erpnext.patches.v6_2.remove_newsletter_duplicates
 erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
 erpnext.patches.v6_3.convert_applicable_territory
@@ -252,3 +252,4 @@
 erpnext.patches.v6_23.update_stopped_status_to_closed
 erpnext.patches.v6_24.repost_valuation_rate_for_serialized_items
 erpnext.patches.v6_24.set_recurring_id
+erpnext.patches.v6_20x.set_compact_print
diff --git a/erpnext/patches/v6_20x/__init__.py b/erpnext/patches/v6_20x/__init__.py
new file mode 100644
index 0000000..baffc48
--- /dev/null
+++ b/erpnext/patches/v6_20x/__init__.py
@@ -0,0 +1 @@
+from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_20x/set_compact_print.py b/erpnext/patches/v6_20x/set_compact_print.py
new file mode 100644
index 0000000..4ba1aea
--- /dev/null
+++ b/erpnext/patches/v6_20x/set_compact_print.py
@@ -0,0 +1,5 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.db.set_value("Features Setup", None, "compact_item_print", 1)
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index d218793..9a44da1 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -36,7 +36,7 @@
 		'fs_exports', 'fs_imports', 'fs_discounts', 'fs_purchase_discounts',
 		'fs_after_sales_installations', 'fs_projects', 'fs_sales_extras',
 		'fs_recurring_invoice', 'fs_pos', 'fs_manufacturing', 'fs_quality',
-		'fs_page_break', 'fs_more_info', 'fs_pos_view'
+		'fs_page_break', 'fs_more_info', 'fs_pos_view', 'compact_item_print'
 	]
 	for f in flds:
 		doc.set(f, 1)
diff --git a/erpnext/startup/notifications.py b/erpnext/startup/notifications.py
index 45f7b81..7555312 100644
--- a/erpnext/startup/notifications.py
+++ b/erpnext/startup/notifications.py
@@ -28,6 +28,7 @@
 			"Delivery Note": {"docstatus": 0},
 			"Stock Entry": {"docstatus": 0},
 			"Material Request": {
+				"docstatus": ("<", 2),
 				"status": ("not in", ("Stopped",)),
 				"per_ordered": ("<", 100)
 			},
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 07ac326..42e8d1b 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -139,8 +139,8 @@
 		return sle_dict
 
 	def on_trash(self):
-		sl_entries = frappe.db.sql("""select serial_no from `tabStock Ledger Entry` 
-			where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'""", 
+		sl_entries = frappe.db.sql("""select serial_no from `tabStock Ledger Entry`
+			where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'""",
 			("%%%s%%" % self.name, self.item_code), as_dict=True)
 
 		# Find the exact match
@@ -149,7 +149,7 @@
 			if self.name.upper() in get_serial_nos(d.serial_no):
 				sle_exists = True
 				break
-			
+
 		if sle_exists:
 			frappe.throw(_("Cannot delete Serial No {0}, as it is used in stock transactions").format(self.name))
 
@@ -208,9 +208,9 @@
 						if not allow_serial_nos_with_different_item(serial_no, sle):
 							frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
 								sle.item_code), SerialNoItemError)
-								
+
 					if sr.warehouse and sle.actual_qty > 0:
-						frappe.throw(_("Serial No {0} has already been received").format(sr.name),
+						frappe.throw(_("Serial No {0} has already been received").format(serial_no),
 							SerialNoDuplicateError)
 
 					if sle.actual_qty < 0:
@@ -229,10 +229,10 @@
 		elif sle.actual_qty < 0 or not item_det.serial_no_series:
 			frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
 				SerialNoRequiredError)
-				
+
 def allow_serial_nos_with_different_item(sle_serial_no, sle):
 	"""
-		Allows same serial nos for raw materials and finished goods 
+		Allows same serial nos for raw materials and finished goods
 		in Manufacture / Repack type Stock Entry
 	"""
 	allow_serial_nos = False
@@ -244,9 +244,9 @@
 					serial_nos = get_serial_nos(d.serial_no)
 					if sle_serial_no in serial_nos:
 						allow_serial_nos = True
-	
+
 	return allow_serial_nos
-			
+
 def update_serial_nos(sle, item_det):
 	if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
 			and item_det.has_serial_no == 1 and item_det.serial_no_series:
diff --git a/erpnext/stock/report/stock_balance/stock_balance.js b/erpnext/stock/report/stock_balance/stock_balance.js
index db334f8..1af32ed 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.js
+++ b/erpnext/stock/report/stock_balance/stock_balance.js
@@ -22,7 +22,40 @@
 			"label": __("Item"),
 			"fieldtype": "Link",
 			"width": "80",
-			"options": "Item"
+			"options": "Item",
+			"reqd": 1,
+			"on_change": function(me) {
+				frappe.query_reports["Stock Balance"].toggle_mandatory_filters(me);
+			}
+		},
+		{
+			"fieldname": "warehouse",
+			"label": __("Warehouse"),
+			"fieldtype": "Link",
+			"width": "80",
+			"options": "Warehouse",
+			"reqd": 1,
+			"on_change": function(me) {
+				frappe.query_reports["Stock Balance"].toggle_mandatory_filters(me);
+			}
+		},
+	],
+
+	"toggle_mandatory_filters": function(me) {
+		var values = me.get_values(false);
+		var item_filter = me.filters_by_name["item_code"];
+		var warehouse_filter = me.filters_by_name["warehouse"];
+
+		if (values.item_code) {
+			warehouse_filter.df.reqd = 0;
+		} else if (values.warehouse) {
+			item_filter.df.reqd = 0;
+		} else {
+			item_filter.df.reqd = 1;
+			warehouse_filter.df.reqd = 1;
 		}
-	]
+
+		item_filter.set_mandatory(values.item_code);
+		warehouse_filter.set_mandatory(values.warehouse);
+	}
 }
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 7dd728f..d465050 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -9,7 +9,7 @@
 def execute(filters=None):
 	if not filters: filters = {}
 
-	columns = get_columns(filters)
+	columns = get_columns()
 	item_map = get_item_details(filters)
 	iwb_map = get_item_warehouse_map(filters)
 
@@ -30,8 +30,8 @@
 
 	return columns, data
 
-def get_columns(filters):
-	"""return columns based on filters"""
+def get_columns():
+	"""return columns"""
 
 	columns = [
 		_("Item")+":Link/Item:100",
@@ -68,9 +68,11 @@
 	if filters.get("item_code"):
 		conditions += " and item_code = '%s'" % frappe.db.escape(filters.get("item_code"), percent=False)
 
+	if filters.get("warehouse"):
+		conditions += " and warehouse = '%s'" % frappe.db.escape(filters.get("warehouse"), percent=False)
+
 	return conditions
 
-#get all details
 def get_stock_ledger_entries(filters):
 	conditions = get_conditions(filters)
 	return frappe.db.sql("""select item_code, warehouse, posting_date, actual_qty, valuation_rate,
@@ -125,9 +127,13 @@
 	return iwb_map
 
 def get_item_details(filters):
-	item_map = {}
-	for d in frappe.db.sql("select name, item_name, stock_uom, item_group, brand, \
-		description from tabItem", as_dict=1):
-		item_map.setdefault(d.name, d)
+	condition = ''
+	value = ()
+	if filters.get("item_code"):
+		condition = "where item_code=%s"
+		value = (filters["item_code"],)
 
-	return item_map
+	items = frappe.db.sql("""select name, item_name, stock_uom, item_group, brand, description
+		from tabItem {condition}""".format(condition=condition), value, as_dict=1)
+
+	return dict((d.name, d) for d in items)