Post GL Entry based on rounded total in Sales/Purchase Invoice (#11542)

diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index b9a7dae..ff58bec 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -17,12 +17,13 @@
 			if(!this.frm.doc.supplier && this.frm.doc.credit_to) {
 				this.frm.set_df_property("credit_to", "print_hide", 0);
 			}
+		} else {
+			this.frm.set_value("disable_rounded_total", frappe.sys_defaults.disable_rounded_total);
 		}
 
 		// formatter for material request item
 		this.frm.set_indicator_formatter('item_code',
 			function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" })
-
 	},
 
 	refresh: function(doc) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 51a099e..857f019 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -2110,6 +2110,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "depends_on": "eval:!doc.disable_rounded_total", 
+   "fieldname": "base_rounded_total", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Rounded Total (Company Currency)", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "Company:company:default_currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "description": "", 
    "fieldname": "base_in_words", 
    "fieldtype": "Data", 
@@ -2235,6 +2267,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "depends_on": "eval:!doc.disable_rounded_total", 
+   "fieldname": "rounded_total", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Rounded Total", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "in_words", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -2328,6 +2392,37 @@
    "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "grand_total", 
+   "fieldname": "disable_rounded_total", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Disable Rounded Total", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
    "collapsible": 1, 
    "collapsible_depends_on": "paid_amount", 
    "columns": 0, 
@@ -3576,7 +3671,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-11-15 01:04:15.308603", 
+ "modified": "2017-11-16 01:04:15.308603", 
  "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 78c5682..626dd92 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -77,8 +77,10 @@
 		if not self.cash_bank_account and flt(self.paid_amount):
 			frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
 
-		if flt(self.paid_amount) + flt(self.write_off_amount) \
-				- flt(self.grand_total) > 1/(10**(self.precision("base_grand_total") + 1)):
+		if (flt(self.paid_amount) + flt(self.write_off_amount)
+			- flt(self.get("rounded_total") or self.grand_total)
+			> 1/(10**(self.precision("base_grand_total") + 1))):
+
 			frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
 
 	def create_remarks(self):
@@ -359,9 +361,10 @@
 		return gl_entries
 
 	def make_supplier_gl_entry(self, gl_entries):
-		if self.grand_total:
+		grand_total = self.rounded_total or self.grand_total
+		if 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(grand_total * self.conversion_rate,
 				self.precision("grand_total"))
 			gl_entries.append(
 				self.get_gl_dict({
@@ -371,7 +374,7 @@
 					"against": self.against_expense_account,
 					"credit": grand_total_in_company_currency,
 					"credit_in_account_currency": grand_total_in_company_currency \
-						if self.party_account_currency==self.company_currency else self.grand_total,
+						if self.party_account_currency==self.company_currency else grand_total,
 					"against_voucher": self.return_against if cint(self.is_return) else self.name,
 					"against_voucher_type": self.doctype,
 				}, self.party_account_currency)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 474329f..baf016d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -35,7 +35,7 @@
 		dl = wrapper
 
 		expected_gl_entries = {
-			"_Test Payable - _TC": [0, 1512.30],
+			"_Test Payable - _TC": [0, 1512.0],
 			"_Test Account Cost for Goods Sold - _TC": [1250, 0],
 			"_Test Account Shipping Charges - _TC": [100, 0],
 			"_Test Account Excise Duty - _TC": [140, 0],
@@ -44,6 +44,7 @@
 			"_Test Account CST - _TC": [29.88, 0],
 			"_Test Account VAT - _TC": [156.25, 0],
 			"_Test Account Discount - _TC": [0, 168.03],
+			"Round Off - _TC": [0, 0.3]
 		}
 		gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
 			where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl.name, as_dict=1)
@@ -233,6 +234,7 @@
 		jv.submit()
 
 		pi = frappe.copy_doc(test_records[0])
+		pi.disable_rounded_total = 1
 		pi.append("advances", {
 			"reference_type": "Journal Entry",
 			"reference_name": jv.name,
@@ -242,6 +244,13 @@
 			"remarks": jv.remark
 		})
 		pi.insert()
+
+		self.assertEqual(pi.outstanding_amount, 1212.30)
+
+		pi.disable_rounded_total = 0
+		pi.save()
+		self.assertEqual(pi.outstanding_amount, 1212.0)
+
 		pi.submit()
 		pi.load_from_db()
 
@@ -249,8 +258,6 @@
 			where reference_type='Purchase Invoice'
 			and reference_name=%s and debit_in_account_currency=300""", pi.name))
 
-		self.assertEqual(pi.outstanding_amount, 1212.30)
-
 		pi.cancel()
 
 		self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
@@ -491,7 +498,7 @@
 		pi.load_from_db()
 		
 		#check outstanding after advance allocation
-		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance))
 		
 		#added to avoid Document has been modified exception
 		jv = frappe.get_doc("Journal Entry", jv.name)
@@ -499,7 +506,7 @@
 		
 		pi.load_from_db()
 		#check outstanding after advance cancellation
-		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance))
 
 	def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
 		pe = frappe.get_doc({
@@ -521,7 +528,7 @@
 		})
 		pe.insert()
 		pe.submit()
-		
+
 		pi = frappe.copy_doc(test_records[0])
 		pi.is_pos = 0
 		pi.append("advances", {
@@ -534,19 +541,19 @@
 		})
 		pi.insert()
 		pi.submit()
-		
+
 		pi.load_from_db()
 
 		#check outstanding after advance allocation
-		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
-		
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance))
+
 		#added to avoid Document has been modified exception
 		pe = frappe.get_doc("Payment Entry", pe.name)
 		pe.cancel()
-		
+
 		pi.load_from_db()
 		#check outstanding after advance cancellation
-		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance))
 
 def unlink_payment_on_cancel_of_invoice(enable=1):
 	accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index db9969d..ee2b554 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -632,9 +632,10 @@
 		return gl_entries
 
 	def make_customer_gl_entry(self, gl_entries):
-		if self.grand_total:
+		grand_total = self.rounded_total or self.grand_total
+		if 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(grand_total * self.conversion_rate,
 				self.precision("grand_total"))
 
 			gl_entries.append(
@@ -645,7 +646,7 @@
 					"against": self.against_income_account,
 					"debit": grand_total_in_company_currency,
 					"debit_in_account_currency": grand_total_in_company_currency \
-						if self.party_account_currency==self.company_currency else self.grand_total,
+						if self.party_account_currency==self.company_currency else grand_total,
 					"against_voucher": self.return_against if cint(self.is_return) else self.name,
 					"against_voucher_type": self.doctype
 				}, self.party_account_currency)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 50d2ce8..12b556b 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -546,7 +546,7 @@
 
 	def test_outstanding(self):
 		w = self.make()
-		self.assertEquals(w.outstanding_amount, w.base_grand_total)
+		self.assertEquals(w.outstanding_amount, w.base_rounded_total)
 
 	def test_payment(self):
 		w = self.make()
@@ -560,7 +560,7 @@
 		jv.insert()
 		jv.submit()
 
-		self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 161.8)
+		self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 162.0)
 
 		link_data = get_dynamic_link_map().get('Sales Invoice', [])
 		link_doctypes = [d.parent for d in link_data]
@@ -569,7 +569,7 @@
 		self.assertTrue(link_doctypes.index('GL Entry') > link_doctypes.index('Journal Entry Account'))
 
 		jv.cancel()
-		self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
+		self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 562.0)
 
 	def test_sales_invoice_gl_entry_without_perpetual_inventory(self):
 		si = frappe.copy_doc(test_records[1])
@@ -848,7 +848,7 @@
 		self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
 			where reference_name=%s and credit_in_account_currency=300""", si.name))
 
-		self.assertEqual(si.outstanding_amount, 261.8)
+		self.assertEqual(si.outstanding_amount, 262.0)
 
 		si.cancel()
 
@@ -1152,7 +1152,8 @@
 		si.load_from_db()
 
 		#check outstanding after advance allocation
-		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
+		self.assertEqual(flt(si.outstanding_amount),
+			flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")))
 
 		#added to avoid Document has been modified exception
 		jv = frappe.get_doc("Journal Entry", jv.name)
@@ -1160,7 +1161,8 @@
 
 		si.load_from_db()
 		#check outstanding after advance cancellation
-		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
+		self.assertEqual(flt(si.outstanding_amount),
+			flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount")))
 
 	def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
 		pe = frappe.get_doc({
@@ -1199,7 +1201,8 @@
 		si.load_from_db()
 
 		#check outstanding after advance allocation
-		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
+		self.assertEqual(flt(si.outstanding_amount),
+			flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")))
 
 		#added to avoid Document has been modified exception
 		pe = frappe.get_doc("Payment Entry", pe.name)
@@ -1207,7 +1210,8 @@
 
 		si.load_from_db()
 		#check outstanding after advance cancellation
-		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
+		self.assertEqual(flt(si.outstanding_amount),
+			flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount")))
 
 	def test_multiple_uom_in_selling(self):
 		frappe.db.sql("""delete from `tabItem Price`
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 74a9000..429d6eb 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -66,9 +66,9 @@
 			if cint(is_paid) == 1:
 				if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
 					if self.cash_bank_account:
-						self.paid_amount = flt(flt(self.grand_total) - flt(self.write_off_amount),
-							self.precision("paid_amount"))
-						self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, self.precision("base_paid_amount"))
+						self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
+						self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
+							self.precision("base_paid_amount"))
 					else:
 						# show message that the amount is not paid
 						self.paid_amount = 0
@@ -598,6 +598,12 @@
 		for item in duplicate_list:
 			self.remove(item)
 
+	def is_rounded_total_disabled(self):
+		if self.meta.get_field("disable_rounded_total"):
+			return self.disable_rounded_total
+		else:
+			return frappe.db.get_single_value("Global Defaults", "disable_rounded_total")
+
 @frappe.whitelist()
 def get_tax_rate(account_head):
 	return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index c1028a5..0e15eee 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -28,8 +28,7 @@
 		super(SellingController, self).onload()
 		if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
 			for item in self.get("items"):
-				item.update(get_bin_details(item.item_code,
-					item.warehouse))
+				item.update(get_bin_details(item.item_code, item.warehouse))
 
 	def validate(self):
 		super(SellingController, self).validate()
@@ -114,14 +113,15 @@
 
 	def set_total_in_words(self):
 		from frappe.utils import money_in_words
-		disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
 
 		if self.meta.get_field("base_in_words"):
-			self.base_in_words = money_in_words(disable_rounded_total and
-				abs(self.base_grand_total) or abs(self.base_rounded_total), self.company_currency)
+			base_amount = abs(self.base_grand_total
+				if self.is_rounded_total_disabled() else self.base_rounded_total)
+			self.base_in_words = money_in_words(base_amount, self.company_currency)
+
 		if self.meta.get_field("in_words"):
-			self.in_words = money_in_words(disable_rounded_total and
-				abs(self.grand_total) or abs(self.rounded_total), self.currency)
+			amount = abs(self.grand_total if self.is_rounded_total_disabled() else self.rounded_total)
+			self.in_words = money_in_words(amount, self.currency)
 
 	def calculate_commission(self):
 		if self.meta.get_field("commission_rate"):
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index e9672df..2b2191c 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -328,14 +328,18 @@
 		self.set_rounded_total()
 
 	def set_rounded_total(self):
-		if frappe.db.get_single_value("Global Defaults", "disable_rounded_total"):
-			self.doc.rounded_total = self.doc.base_rounded_total = 0
-			return
-
 		if self.doc.meta.get_field("rounded_total"):
+			if self.doc.is_rounded_total_disabled():
+				self.doc.rounded_total = self.doc.base_rounded_total = 0
+				return
+
 			self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
 				self.doc.currency, self.doc.precision("rounded_total"))
 
+			#if print_in_rate is set, we would have already calculated rounding adjustment
+			self.doc.rounding_adjustment += flt(self.doc.rounded_total - self.doc.grand_total,
+				self.doc.precision("rounding_adjustment"))
+
 		if self.doc.meta.get_field("base_rounded_total"):
 			company_currency = erpnext.get_company_currency(self.doc.company)
 
@@ -343,6 +347,9 @@
 				round_based_on_smallest_currency_fraction(self.doc.base_grand_total,
 					company_currency, self.doc.precision("base_rounded_total"))
 
+			self.doc.base_rounding_adjustment += flt(self.doc.base_rounded_total - self.doc.base_grand_total,
+				self.doc.precision("base_rounding_adjustment"))
+
 	def _cleanup(self):
 		for tax in self.doc.get("taxes"):
 			tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(',', ':'))
@@ -404,7 +411,8 @@
 					actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100
 					actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
 
-			return flt(self.doc.grand_total - sum(actual_taxes_dict.values()), self.doc.precision("grand_total"))
+			return flt(self.doc.grand_total - sum(actual_taxes_dict.values()),
+				self.doc.precision("grand_total"))
 
 
 	def calculate_total_advance(self):
@@ -442,30 +450,31 @@
 		self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
 		self._set_in_company_currency(self.doc, ['write_off_amount'])
 
-		if self.doc.party_account_currency == self.doc.currency:
-			total_amount_to_pay = flt(self.doc.grand_total  - self.doc.total_advance
-				- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
-		else:
-			total_amount_to_pay = flt(flt(self.doc.grand_total *
-				self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance
-					- flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
+		if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
+			grand_total = self.doc.rounded_total or self.doc.grand_total
+			if self.doc.party_account_currency == self.doc.currency:
+				total_amount_to_pay = flt(grand_total  - self.doc.total_advance
+					- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
+			else:
+				total_amount_to_pay = flt(flt(grand_total *
+					self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance
+						- flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
 
-		if self.doc.doctype == "Sales Invoice":			
 			self.doc.round_floats_in(self.doc, ["paid_amount"])
-			self.calculate_write_off_amount()
-			self.calculate_change_amount()
-			
+			change_amount = 0
+
+			if self.doc.doctype == "Sales Invoice":
+				self.calculate_write_off_amount()
+				self.calculate_change_amount()
+				change_amount = self.doc.change_amount \
+					if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount
+
 			paid_amount = self.doc.paid_amount \
 				if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount
-			
-			change_amount = self.doc.change_amount \
-				if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount
 
-			self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
-				flt(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"))
+			self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(change_amount),
+				self.doc.precision("outstanding_amount"))
 
 	def calculate_paid_amount(self):
 		paid_amount = base_paid_amount = 0.0
@@ -485,7 +494,9 @@
 	def calculate_change_amount(self):
 		self.doc.change_amount = 0.0
 		self.doc.base_change_amount = 0.0
-		if self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \
+
+		if self.doc.doctype == "Sales Invoice" \
+			and self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \
 			and any([d.type == "Cash" for d in self.doc.payments]):
 
 			self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total +
@@ -496,8 +507,8 @@
 
 	def calculate_write_off_amount(self):
 		if flt(self.doc.change_amount) > 0:
-			self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount,
-				self.doc.precision("write_off_amount"))
+			self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount
+				+ self.doc.change_amount, self.doc.precision("write_off_amount"))
 			self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate,
 				self.doc.precision("base_write_off_amount"))
 
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 05c323b..afdc873 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -422,13 +422,27 @@
 		frappe.model.round_floats_in(this.frm.doc, ["grand_total", "base_grand_total"]);
 
 		// rounded totals
-		this.set_rounded_total()
+		this.set_rounded_total();
 	},
 
 	set_rounded_total: function() {
+		var disable_rounded_total = 0;
+		if(frappe.meta.get_docfield(this.frm.doc.doctype, "disable_rounded_total", this.frm.doc.name)) {
+			disable_rounded_total = this.frm.doc.disable_rounded_total;
+		} else if (frappe.sys_defaults.disable_rounded_total) {
+			disable_rounded_total = frappe.sys_defaults.disable_rounded_total;
+		}
+		if(disable_rounded_total) {
+			this.frm.doc.rounded_total = 0;
+			this.frm.doc.base_rounded_total = 0;
+			return;
+		}
+
 		if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
 			this.frm.doc.rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.grand_total,
 				this.frm.doc.currency, precision("rounded_total"));
+			this.frm.doc.rounding_adjustment += flt(this.frm.doc.rounded_total - this.frm.doc.grand_total,
+				precision("rounding_adjustment"));
 		}
 		if(frappe.meta.get_docfield(this.frm.doc.doctype, "base_rounded_total", this.frm.doc.name)) {
 			var company_currency = this.get_company_currency();
@@ -436,6 +450,9 @@
 			this.frm.doc.base_rounded_total =
 				round_based_on_smallest_currency_fraction(this.frm.doc.base_grand_total,
 					company_currency, precision("base_rounded_total"));
+
+			this.frm.doc.base_rounding_adjustment += flt(this.frm.doc.base_rounded_total -
+				this.frm.doc.base_grand_total, precision("rounding_adjustment"));
 		}
 	},
 
@@ -560,20 +577,22 @@
 		if(this.frm.doc.is_return || this.frm.doc.docstatus > 0) return;
 
 		frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
-		if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
-			var total_amount_to_pay = flt((this.frm.doc.grand_total - this.frm.doc.total_advance
-				- this.frm.doc.write_off_amount), precision("grand_total"));
-		} else {
-			var total_amount_to_pay = flt(
-				(flt(this.frm.doc.grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
-					- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
-				precision("base_grand_total")
-			);
-		}
 
-		if(this.frm.doc.doctype == "Sales Invoice" || this.frm.doc.doctype == "Purchase Invoice") {
+		if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
+			var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+
+			if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
+				var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
+					- this.frm.doc.write_off_amount), precision("grand_total"));
+			} else {
+				var total_amount_to_pay = flt(
+					(flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
+						- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
+					precision("base_grand_total")
+				);
+			}
+
 			frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]);
-
 			this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
 
 			if(this.frm.refresh_field){
@@ -581,11 +600,10 @@
 				this.frm.refresh_field("base_paid_amount");
 			}
 
-			if(this.frm.doc.doctype == "Sales Invoice"){
+			if(this.frm.doc.doctype == "Sales Invoice") {
 				this.set_default_payment(total_amount_to_pay, update_paid_amount);
 				this.calculate_paid_amount();
 			}
-
 			this.calculate_change_amount();
 
 			var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ?
@@ -593,9 +611,6 @@
 
 			this.frm.doc.outstanding_amount =  flt(total_amount_to_pay - flt(paid_amount) +
 				flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate), precision("outstanding_amount"));
-
-		} else if(this.frm.doc.doctype == "Purchase Invoice") {
-			this.frm.doc.outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount"));
 		}
 	},
 
@@ -636,7 +651,9 @@
 	calculate_change_amount: function(){
 		this.frm.doc.change_amount = 0.0;
 		this.frm.doc.base_change_amount = 0.0;
-		if(this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
+		if(this.frm.doc.doctype == "Sales Invoice"
+			&& this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
+
 			var payment_types = $.map(this.frm.doc.payments, function(d) { return d.type; });
 			if (in_list(payment_types, 'Cash')) {
 				this.frm.doc.change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total +
diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py
index 9c6eb82..a39e246 100644
--- a/erpnext/setup/doctype/global_defaults/global_defaults.py
+++ b/erpnext/setup/doctype/global_defaults/global_defaults.py
@@ -57,7 +57,8 @@
 		self.disable_rounded_total = cint(self.disable_rounded_total)
 
 		# Make property setters to hide rounded total fields
-		for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note"):
+		for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
+			"Supplier Quotation", "Purchase Order"):
 			make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check")
 			make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check")
 
@@ -69,6 +70,6 @@
 
 		# Make property setters to hide in words fields
 		for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
-						"Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"):
+				"Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"):
 			make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check")
 			make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check")