Merge branch 'develop'
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index f701552..5886dcc 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
 from __future__ import unicode_literals
-__version__ = '4.24.0'
+__version__ = '4.24.1'
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index a50d69e..1cb26fd 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -244,7 +244,7 @@
 		cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, true);
 	}
 
-	item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse']
+	item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'actual_batch_qty', 'expense_account', 'warehouse']
 	cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_stock,
 		(cint(doc.update_stock)==1 ? true : false));
 
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 2baa06a..d545f37 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -341,6 +341,19 @@
   }, 
   {
    "allow_on_submit": 1, 
+   "fieldname": "actual_batch_qty", 
+   "fieldtype": "Float", 
+   "label": "Available Batch Qty at Warehouse", 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_width": "150px", 
+   "read_only": 1, 
+   "width": "150px"
+  }, 
+  {
+   "allow_on_submit": 1, 
    "fieldname": "actual_qty", 
    "fieldtype": "Float", 
    "label": "Available Qty at Warehouse", 
@@ -439,7 +452,7 @@
  ], 
  "idx": 1, 
  "istable": 1, 
- "modified": "2014-09-09 05:35:36.019576", 
+ "modified": "2015-03-10 14:56:45.641026", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Sales Invoice Item", 
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index fcc350a..bb7e852 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -185,6 +185,7 @@
 
 		self.calculate_net_total()
 		self.calculate_taxes()
+		self.manipulate_grand_total_for_inclusive_tax()
 		self.calculate_totals()
 		self._cleanup()
 
@@ -353,6 +354,22 @@
 			self.precision(base_field, item))
 		item.set(base_field, value_in_company_currency)
 
+	def manipulate_grand_total_for_inclusive_tax(self):
+		# if fully inclusive taxes and diff
+		if (self.meta.get_field("net_total_export") and self.tax_doclist
+			and all(cint(t.included_in_print_rate) for t in self.tax_doclist)):
+
+			last_tax = self.tax_doclist[-1]
+
+			diff = self.net_total_export - flt(last_tax.total / self.conversion_rate,
+				self.precision("grand_total_export"))
+
+			if diff and abs(diff) <= (2.0 / 10**(self.precision("tax_amount", last_tax))):
+				adjustment_amount = flt(diff * self.conversion_rate, self.precision("tax_amount", last_tax))
+				last_tax.tax_amount += adjustment_amount
+				last_tax.tax_amount_after_discount_amount += adjustment_amount
+				last_tax.total += adjustment_amount
+
 	def calculate_total_advance(self, parenttype, advance_parentfield):
 		if self.doctype == parenttype and self.docstatus < 2:
 			sum_of_allocated_amount = sum([flt(adv.allocated_amount, self.precision("allocated_amount", adv))
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 017f80e..15ed392 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -5,7 +5,7 @@
 app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
 app_icon = "icon-th"
 app_color = "#e74c3c"
-app_version = "4.24.0"
+app_version = "4.24.1"
 
 error_report_email = "support@erpnext.com"
 
diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js
index ebdb136..ba0fa40 100644
--- a/erpnext/public/js/transaction.js
+++ b/erpnext/public/js/transaction.js
@@ -632,6 +632,7 @@
 		this.determine_exclusive_rate && this.determine_exclusive_rate();
 		this.calculate_net_total();
 		this.calculate_taxes();
+		this.manipulate_grand_total_for_inclusive_tax && this.manipulate_grand_total_for_inclusive_tax();
 		this.calculate_totals();
 		this._cleanup();
 
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 5a7ed08..e905de1 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -215,6 +215,8 @@
 	},
 
 	warehouse: function(doc, cdt, cdn) {
+		var me = this;
+		this.batch_no(doc, cdt, cdn);
 		var item = frappe.get_doc(cdt, cdn);
 		if(item.item_code && item.warehouse) {
 			return this.frm.call({
@@ -456,6 +458,29 @@
 			});
 	},
 
+	manipulate_grand_total_for_inclusive_tax: function() {
+		// if fully inclusive taxes and diff
+		if (this.frm.tax_doclist.length) {
+			var all_inclusive = frappe.utils.all(this.frm.tax_doclist.map(function(d) {
+				return cint(d.included_in_print_rate);
+			}));
+
+			if (all_inclusive) {
+				var last_tax = this.frm.tax_doclist.slice(-1)[0];
+
+				var diff = this.frm.doc.net_total_export
+					- flt(last_tax.total / this.frm.doc.conversion_rate, precision("grand_total_export"));
+
+				if ( diff && Math.abs(diff) <= (2.0 / Math.pow(10, precision("tax_amount", last_tax))) ) {
+					var adjustment_amount = flt(diff * this.frm.doc.conversion_rate, precision("tax_amount", last_tax));
+					last_tax.tax_amount += adjustment_amount;
+					last_tax.tax_amount_after_discount += adjustment_amount;
+					last_tax.total += adjustment_amount;
+				}
+			}
+		}
+	},
+
 	_cleanup: function() {
 		this._super();
 		this.frm.doc.in_words = this.frm.doc.in_words_export = "";
@@ -476,6 +501,21 @@
 		}
 	},
 
+	batch_no: function(doc, cdt, cdn) {
+		var me = this;
+		var item = frappe.get_doc(cdt, cdn);
+	    return this.frm.call({
+	        method: "erpnext.stock.get_item_details.get_batch_qty",
+	        child: item,
+	        args: {
+	           "batch_no": item.batch_no,
+	           "warehouse": item.warehouse,
+	           "item_code": item.item_code
+	        },
+	         "fieldname": "actual_batch_qty"
+	    });
+	},
+
 	set_dynamic_labels: function() {
 		this._super();
 		this.set_sales_bom_help(this.frm.doc);
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index a5fe469..e2385f5 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -316,6 +316,19 @@
   }, 
   {
    "allow_on_submit": 1, 
+   "fieldname": "actual_batch_qty", 
+   "fieldtype": "Float", 
+   "label": "Available Batch Qty at Warehouse", 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_width": "150px", 
+   "read_only": 1, 
+   "width": "150px"
+  }, 
+  {
+   "allow_on_submit": 1, 
    "fieldname": "actual_qty", 
    "fieldtype": "Float", 
    "label": "Available Qty at Warehouse", 
@@ -426,7 +439,7 @@
  ], 
  "idx": 1, 
  "istable": 1, 
- "modified": "2014-09-09 05:35:37.460939", 
+ "modified": "2015-03-10 12:21:17.028911", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Delivery Note Item", 
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 6f9839d..6d01c33 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -278,6 +278,15 @@
 			"qty": cint(args.qty)
 		}))
 
+def get_actual_batch_qty(batch_no,warehouse,item_code):
+        actual_batch_qty = 0
+        if batch_no:
+            actual_batch_qty = flt(frappe.db.sql("""select sum(actual_qty)
+				from `tabStock Ledger Entry`
+				where warehouse=%s and item_code=%s and batch_no=%s""",
+				(warehouse, item_code, batch_no))[0][0])
+        return actual_batch_qty
+
 @frappe.whitelist()
 def get_conversion_factor(item_code, uom):
 	return {"conversion_factor": frappe.db.get_value("UOM Conversion Detail",
@@ -294,6 +303,12 @@
 		["projected_qty", "actual_qty"], as_dict=True) or {}
 
 @frappe.whitelist()
+def get_batch_qty(batch_no,warehouse,item_code):
+	actual_batch_qty = get_actual_batch_qty(batch_no,warehouse,item_code)
+	if batch_no:
+		return {'actual_batch_qty': actual_batch_qty}
+	
+@frappe.whitelist()
 def apply_price_list(args):
 	"""
 		args = {
diff --git a/setup.py b/setup.py
index 44bafc9..6225753 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
 from setuptools import setup, find_packages
 import os
 
-version = "4.24.0"
+version = "4.24.1"
 
 with open("requirements.txt", "r") as f:
 	install_requires = f.readlines()