Merge branch 'develop'
diff --git a/.travis.yml b/.travis.yml
index 31f4408..9cad59f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,5 @@
 language: python
+dist: trusty
 
 python:
   - "2.7"
@@ -11,10 +12,14 @@
   - "sh -e /etc/init.d/xvfb start"
 
 install:
-  - sudo apt-get purge -y mysql-common
-  - wget https://raw.githubusercontent.com/frappe/bench/master/install_scripts/setup_frappe.sh
-  - sudo bash setup_frappe.sh --skip-setup-bench --mysql-root-password travis --bench-branch develop
-  - sudo pip install --upgrade pip
+  - sudo apt-get purge -y mysql-common mysql-server mysql-client
+  # - wget https://raw.githubusercontent.com/frappe/bench/master/install_scripts/setup_frappe.sh
+  # - sudo bash setup_frappe.sh --skip-setup-bench --mysql-root-password travis --bench-branch develop
+  - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
+  - sudo python install.py --develop --user travis --without-bench-setup
+  - sudo pip install -e ~/bench
+
+  # - sudo pip install --upgrade pip
   - rm $TRAVIS_BUILD_DIR/.git/shallow
   - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh
   - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/
@@ -30,7 +35,7 @@
   - bench --verbose run-tests --driver Firefox
 
 before_script:
-  - mysql -e 'create database test_frappe'
+  - mysql -u root -ptravis -e 'create database test_frappe'
   - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis
   - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
 
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index d6310b8..11232b3 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -2,7 +2,7 @@
 from __future__ import unicode_literals
 import frappe
 
-__version__ = '7.0.16'
+__version__ = '7.0.17'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 6c04cf5..175ebda 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -569,10 +569,9 @@
 @frappe.whitelist()
 def get_reference_details(reference_doctype, reference_name, party_account_currency):
 	total_amount = outstanding_amount = exchange_rate = None
+	ref_doc = frappe.get_doc(reference_doctype, reference_name)
 	
 	if reference_doctype != "Journal Entry":
-		ref_doc = frappe.get_doc(reference_doctype, reference_name)
-
 		if party_account_currency == ref_doc.company_currency:
 			total_amount = ref_doc.base_grand_total
 			exchange_rate = 1
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index b284619..f055140 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -87,15 +87,6 @@
 	def before_save(self):
 		set_account_for_mode_of_payment(self)
 
-	def update_change_amount(self):
-		self.base_paid_amount = 0.0
-		if self.paid_amount:
-			self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, self.precision("base_paid_amount"))
-			self.change_amount = self.base_change_amount = 0.0
-			if self.paid_amount > self.grand_total:
-				self.change_amount = flt(self.paid_amount - self.grand_total, self.precision("change_amount"))
-				self.base_change_amount = flt(self.change_amount * self.conversion_rate, self.precision("base_change_amount"))
-
 	def on_submit(self):
 		if not self.recurring_id:
 			frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
@@ -110,6 +101,7 @@
 		self.update_status_updater_args()
 		self.update_prevdoc_status()
 		self.update_billing_status_in_dn()
+		self.clear_unallocated_mode_of_payments()
 
 		# Updating stock ledger should always be called after updating prevdoc status,
 		# because updating reserved qty in bin depends upon updated delivered qty in SO
@@ -296,6 +288,12 @@
 			frappe.throw(_("Debit To account must be a Receivable account"))
 
 		self.party_account_currency = account.account_currency
+		
+	def clear_unallocated_mode_of_payments(self):
+		self.set("payments", self.get("payments", {"amount": ["not in", [0, None, ""]]}))
+
+		frappe.db.sql("""delete from `tabSales Invoice Payment` where parent = %s
+			and amount = 0""", self.name)
 
 	def validate_with_previous_doc(self):
 		super(SalesInvoice, self).validate_with_previous_doc({
@@ -504,6 +502,7 @@
 		gl_entries = merge_similar_entries(gl_entries)
 
 		self.make_pos_gl_entries(gl_entries)
+		self.make_gle_for_change(gl_entries)
 
 		self.make_write_off_gl_entry(gl_entries)
 
@@ -578,27 +577,24 @@
 
 	def make_pos_gl_entries(self, gl_entries):
 		if cint(self.is_pos) and self.paid_amount:
-			# POS, make payment entries
-			gl_entries.append(
-				self.get_gl_dict({
-					"account": self.debit_to,
-					"party_type": "Customer",
-					"party": self.customer,
-					"against": self.cash_bank_account,
-					"credit": flt(self.base_paid_amount - self.base_change_amount),
-					"credit_in_account_currency": flt(self.base_paid_amount - self.base_change_amount) \
-						if self.party_account_currency==self.company_currency else flt(self.paid_amount - self.change_amount),
-					"against_voucher": self.return_against if cint(self.is_return) else self.name,
-					"against_voucher_type": self.doctype,
-				}, self.party_account_currency)
-			)
-
-			cash_account = ''
 			for payment_mode in self.payments:
-				if payment_mode.type == 'Cash':
-					cash_account = payment_mode.account
-
 				if payment_mode.base_amount > 0:
+					# POS, make payment entries
+					gl_entries.append(
+						self.get_gl_dict({
+							"account": self.debit_to,
+							"party_type": "Customer",
+							"party": self.customer,
+							"against": payment_mode.account,
+							"credit": payment_mode.base_amount,
+							"credit_in_account_currency": payment_mode.base_amount \
+								if self.party_account_currency==self.company_currency \
+								else payment_mode.amount,
+							"against_voucher": self.return_against if cint(self.is_return) else self.name,
+							"against_voucher_type": self.doctype,
+						}, self.party_account_currency)
+					)
+					
 					payment_mode_account_currency = get_account_currency(payment_mode.account)
 					gl_entries.append(
 						self.get_gl_dict({
@@ -609,20 +605,44 @@
 								if payment_mode_account_currency==self.company_currency else payment_mode.amount
 						}, payment_mode_account_currency)
 					)
-
-			if self.change_amount:
-				cash_account = cash_account or self.payments[0].account
-				cash_account_currency = get_account_currency(cash_account)
+				
+	def make_gle_for_change(self, gl_entries):
+		if cint(self.is_pos) and self.change_amount:
+			cash_account = self.get_cash_account()
+			if cash_account:
+				gl_entries.append(
+					self.get_gl_dict({
+						"account": self.debit_to,
+						"party_type": "Customer",
+						"party": self.customer,
+						"against": cash_account,
+						"debit": flt(self.base_change_amount),
+						"debit_in_account_currency": flt(self.base_change_amount) \
+							if self.party_account_currency==self.company_currency else flt(self.change_amount),
+						"against_voucher": self.return_against if cint(self.is_return) else self.name,
+						"against_voucher_type": self.doctype
+					}, self.party_account_currency)
+				)
+				
 				gl_entries.append(
 					self.get_gl_dict({
 						"account": cash_account,
 						"against": self.customer,
-						"credit": self.base_change_amount,
-						"credit_in_account_currency": self.base_change_amount \
-							if payment_mode_account_currency==self.company_currency else self.change_amount
-					}, payment_mode_account_currency)
+						"credit": self.base_change_amount
+					})
 				)
-
+		
+				
+	def get_cash_account(self):
+		cash_account = [d.account for d in self.payments if d.type=="Cash"]
+		if cash_account:
+			cash_account = cash_account[0]
+		else:
+			cash_account = frappe.db.get_value("Account", 
+				filters={"company": self.company, "account_type": "Cash", "is_group": 0})
+				
+		return cash_account
+		
 	def make_write_off_gl_entry(self, gl_entries):
 		# write off entries, applicable if only pos
 		if self.write_off_account and self.write_off_amount:
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index e7eee5f..dd28059 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -503,7 +503,8 @@
 			[pos["taxes"][1]["account_head"], 0.0, 50.0],
 			[stock_in_hand, 0.0, abs(sle.stock_value_difference)],
 			[pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0],
-			[si.debit_to, 0.0, si.paid_amount],
+			[si.debit_to, 0.0, 300.0],
+			[si.debit_to, 0.0, cash_amount],
 			["_Test Bank - _TC", 300.0, 0.0],
 			["Cash - _TC", cash_amount, 0.0]
 		])
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index a0fcb63..419d83f 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -27,6 +27,12 @@
 					"description": _("Bank/Cash transactions against party or for internal transfer")
 				},
 				{
+					"type": "page",
+					"name": "pos",
+					"label": _("POS"),
+					"description": _("Point of Sale")
+				},
+				{
 					"type": "report",
 					"name": "Accounts Receivable",
 					"doctype": "Sales Invoice",	
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index eb75dee..28b2f7c 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -440,33 +440,32 @@
 			paid_amount = self.doc.paid_amount \
 				if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount
 
-			self.doc.outstanding_amount = 0
-			if total_amount_to_pay > paid_amount:
-				self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount),
-					self.doc.precision("outstanding_amount"))
-			self.change_amount()
+			self.calculate_change_amount()
 
+			self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
+				flt(self.doc.change_amount), self.doc.precision("outstanding_amount"))
+					
 		elif self.doc.doctype == "Purchase Invoice":
 			self.doc.outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount"))
 		
 	def calculate_paid_amount(self):
 		paid_amount = base_paid_amount = 0.0
 		for payment in self.doc.get('payments'):
-			payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
-			paid_amount += payment.amount
-			base_paid_amount += payment.base_amount
+			if flt(payment.amount) > 0:
+				payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
+				paid_amount += payment.amount
+				base_paid_amount += payment.base_amount
 
 		self.doc.paid_amount = flt(paid_amount, self.doc.precision("paid_amount"))
 		self.doc.base_paid_amount = flt(base_paid_amount, self.doc.precision("base_paid_amount"))
 
-	def change_amount(self):
-		change_amount = 0.0
+	def calculate_change_amount(self):
+		self.doc.change_amount = 0.0
 		if self.doc.paid_amount > self.doc.grand_total:
-			change_amount = flt(self.doc.paid_amount - self.doc.grand_total, 
-				self.doc.precision("change_amount"))
+			self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total + 
+				self.doc.write_off_amount, self.doc.precision("change_amount"))
 
-		self.doc.change_amount = change_amount;
-		self.doc.base_change_amount = flt(change_amount * self.doc.conversion_rate, 
+		self.doc.base_change_amount = flt(self.doc.change_amount * self.doc.conversion_rate, 
 			self.doc.precision("base_change_amount"))
 
 	def calculate_margin(self, item):
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 2b173bf..0f6dae6 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -540,7 +540,7 @@
 	po = frappe.get_doc('Production Order', source_name)
 	ts = po.make_time_logs(open_new=True)
 
-	if not ts.get('time_logs'):
+	if not ts or not ts.get('time_logs'):
 		frappe.throw(_("Already completed"))
 
 	return ts
diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
index 4770781..5fbcf1e 100644
--- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
+++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
@@ -451,10 +451,8 @@
 					"company": self.company,
 					"requested_by": frappe.session.user
 				})
-				if item_wrapper.default_bom:
-					material_request.update({"material_request_type": "Manufacture"}) 
-				else:
-					material_request.update({"material_request_type": "Purchase"})
+				material_request.update({"material_request_type": item_wrapper.default_material_request_type})
+
 				for sales_order, requested_qty in items_to_be_requested[item].items():
 					material_request.append("items", {
 						"doctype": "Material Request Item",
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 97f5bd5..4d3932f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -306,4 +306,5 @@
 erpnext.patches.v7_0.fix_nonwarehouse_ledger_gl_entries_for_transactions
 erpnext.patches.v7_0.remove_old_earning_deduction_doctypes
 erpnext.patches.v7_0.make_guardian
-erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher
\ No newline at end of file
+erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher
+execute:frappe.db.sql("update `tabItem` set default_material_request_type= case when default_bom is not null then 'Manufacture' else 'Purchase' end")
diff --git a/erpnext/patches/v7_0/make_guardian.py b/erpnext/patches/v7_0/make_guardian.py
index 15b9bd1..f654b79 100644
--- a/erpnext/patches/v7_0/make_guardian.py
+++ b/erpnext/patches/v7_0/make_guardian.py
@@ -6,6 +6,7 @@
 		frappe.reload_doc("schools", "doctype", "student")
 		frappe.reload_doc("schools", "doctype", "guardian")
 		frappe.reload_doc("schools", "doctype", "guardian_interest")
+		frappe.reload_doc("hr", "doctype", "interest")
 	
 		students = frappe.get_all("Student", fields=["name", "father_name", "father_email_id", 
 			"mother_name", "mother_email_id"])
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 34c4557..576bc71 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -561,22 +561,18 @@
 				this.calculate_paid_amount()
 			}
 
+			this.calculate_change_amount()
 			var outstanding_amount = 0.0
 
 			var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ?
 				this.frm.doc.paid_amount : this.frm.doc.base_paid_amount;
 
-			if (total_amount_to_pay > paid_amount){
-				outstanding_amount =  flt(total_amount_to_pay - flt(paid_amount),
-					precision("outstanding_amount"));
-			}
+			this.frm.doc.outstanding_amount =  flt(total_amount_to_pay - flt(paid_amount) + 
+				flt(this.frm.doc.change_amount), precision("outstanding_amount"));
 
 		} else if(this.frm.doc.doctype == "Purchase Invoice") {
-			var outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount"));
-		}
-
-		this.frm.doc.outstanding_amount = outstanding_amount;
-		this.calculate_change_amount()
+			this.frm.doc.outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount"));
+		}		
 	},
 
 	set_default_payment: function(total_amount_to_pay, update_paid_amount){
@@ -610,15 +606,13 @@
 	},
 
 	calculate_change_amount: function(){
-		var change_amount = 0.0;
+		this.frm.doc.change_amount = 0.0;
 		if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
-			change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total,
-				precision("change_amount"))
+			this.frm.doc.change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total + 
+				this.frm.doc.write_off_amount, precision("change_amount"));
 		}
 
-		this.frm.doc.change_amount = flt(change_amount,
-			precision("change_amount"))
-		this.frm.doc.base_change_amount = flt(change_amount * this.frm.doc.conversion_rate,
-			precision("base_change_amount"))
+		this.frm.doc.base_change_amount = flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate,
+			precision("base_change_amount"));
 	},
 })
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 17e379c..1f793d1 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -116,6 +116,14 @@
 	}
 });
 
+frappe.ui.form.on('Item Reorder', {
+	reorder_levels_add: function(frm, cdt, cdn) {
+		var row = frappe.get_doc(cdt, cdn);
+		type = frm.doc.default_material_request_type
+		row.material_request_type = (type == 'Material Transfer')? 'Transfer' : type;
+	}
+})
+
 $.extend(erpnext.item, {
 	setup_queries: function(frm) {
 		frm.fields_dict['expense_account'].get_query = function(doc) {
@@ -351,6 +359,7 @@
 	}
 });
 
+
 cur_frm.add_fetch('attribute', 'numeric_values', 'numeric_values');
 cur_frm.add_fetch('attribute', 'from_range', 'from_range');
 cur_frm.add_fetch('attribute', 'to_range', 'to_range');
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index e2aa274..ab3f601 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -709,6 +709,33 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "default": "Purchase", 
+   "fieldname": "default_material_request_type", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Default Material Request Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Purchase\nMaterial Transfer\nMaterial Issue\nManufacture", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "depends_on": "is_stock_item", 
    "fieldname": "column_break1", 
    "fieldtype": "Column Break", 
@@ -2308,7 +2335,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 1, 
- "modified": "2016-07-21 18:44:10.230372", 
+ "modified": "2016-07-28 19:12:27.253074", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item", 
diff --git a/erpnext/stock/doctype/item_reorder/item_reorder.json b/erpnext/stock/doctype/item_reorder/item_reorder.json
index 4c98c3f..43eb98d 100644
--- a/erpnext/stock/doctype/item_reorder/item_reorder.json
+++ b/erpnext/stock/doctype/item_reorder/item_reorder.json
@@ -124,8 +124,9 @@
    "label": "Material Request Type", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "Purchase\nTransfer", 
+   "options": "Purchase\nTransfer\nMaterial Issue\nManufacture", 
    "permlevel": 0, 
+   "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
@@ -146,7 +147,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2016-07-11 03:59:06.870780", 
+ "modified": "2016-07-28 19:15:38.270046", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item Reorder", 
diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py
index ad810a9..5131381 100644
--- a/erpnext/stock/reorder_item.py
+++ b/erpnext/stock/reorder_item.py
@@ -16,7 +16,7 @@
 		return _reorder_item()
 
 def _reorder_item():
-	material_requests = {"Purchase": {}, "Transfer": {}}
+	material_requests = {"Purchase": {}, "Transfer": {}, "Material Issue": {}, "Manufacture": {}}
 	warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse`
 		where disabled=0"""))
 	default_company = (erpnext.get_default_company() or