Merge pull request #1316 from nabinhait/hotfix

rounding and divisional loss
diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py
index 0b8ad46..06b7a3a 100644
--- a/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -358,7 +358,8 @@
 					# expense will be booked in sales invoice
 					stock_item_and_auto_accounting_for_stock = True
 					
-					valuation_amt = item.amount + item.item_tax_amount + item.rm_supp_cost
+					valuation_amt = flt(item.amount + item.item_tax_amount + item.rm_supp_cost, 
+						self.precision("amount", item))
 					
 					gl_entries.append(
 						self.get_gl_dict({
diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py
index 8d33327..e5b0b9d 100644
--- a/controllers/accounts_controller.py
+++ b/controllers/accounts_controller.py
@@ -223,20 +223,22 @@
 				_on_previous_row_error("1 - %d" % (tax.row_id,))
 				
 	def calculate_taxes(self):
-		for item in self.item_doclist:
+		# maintain actual tax rate based on idx
+		actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist 
+			if tax.charge_type == "Actual"])
+			
+		for n, item in enumerate(self.item_doclist):
 			item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
 
 			for i, tax in enumerate(self.tax_doclist):
 				# tax_amount represents the amount of tax for the current step
 				current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
-				
-				# case when net total is 0 but there is an actual type charge
-				# in this case add the actual amount to tax.tax_amount
-				# and tax.grand_total_for_current_item for the first such iteration
-				if tax.charge_type=="Actual" and \
-						not (current_tax_amount or self.doc.net_total or tax.tax_amount):
-					zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax))
-					current_tax_amount += zero_net_total_adjustment
+					
+				# Adjust divisional loss to the last item
+				if tax.charge_type == "Actual":
+					actual_tax_dict[tax.idx] -= current_tax_amount
+					if n == len(self.item_doclist) - 1:
+						current_tax_amount += actual_tax_dict[tax.idx]
 
 				# store tax_amount for current item as it will be used for
 				# charge type = 'On Previous Row Amount'
@@ -248,7 +250,8 @@
 				if tax.category:
 					# if just for valuation, do not add the tax amount in total
 					# hence, setting it as 0 for further steps
-					current_tax_amount = 0.0 if (tax.category == "Valuation") else current_tax_amount
+					current_tax_amount = 0.0 if (tax.category == "Valuation") \
+						else current_tax_amount
 					
 					current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
 				
@@ -267,6 +270,11 @@
 				# in tax.total, accumulate grand total of each item
 				tax.total += tax.grand_total_for_current_item
 				
+				# set precision in the last item iteration
+				if n == len(self.item_doclist) - 1:
+					tax.total = flt(tax.total, self.precision("total", tax))
+					tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
+				
 	def get_current_tax_amount(self, item, tax, item_tax_map):
 		tax_rate = self._get_tax_rate(tax, item_tax_map)
 		current_tax_amount = 0.0
diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py
index 3c6981d..7954ca0 100644
--- a/controllers/buying_controller.py
+++ b/controllers/buying_controller.py
@@ -175,23 +175,31 @@
 		stock_items = self.get_stock_items()
 		
 		stock_items_qty, stock_items_amount = 0, 0
+		last_stock_item_idx = 1
 		for d in self.doclist.get({"parentfield": parentfield}):
 			if d.item_code and d.item_code in stock_items:
 				stock_items_qty += flt(d.qty)
 				stock_items_amount += flt(d.amount)
+				last_stock_item_idx = d.idx
 			
 		total_valuation_amount = sum([flt(d.tax_amount) for d in 
 			self.doclist.get({"parentfield": "purchase_tax_details"}) 
 			if d.category in ["Valuation", "Valuation and Total"]])
 			
-			
-		for item in self.doclist.get({"parentfield": parentfield}):
+		
+		valuation_amount_adjustment = total_valuation_amount
+		for i, item in enumerate(self.doclist.get({"parentfield": parentfield})):
 			if item.item_code and item.qty and item.item_code in stock_items:
 				item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
 					else flt(item.qty) / stock_items_qty
 				
-				item.item_tax_amount = flt(item_proportion * total_valuation_amount, 
-					self.precision("item_tax_amount", item))
+				if i == (last_stock_item_idx - 1):
+					item.item_tax_amount = flt(valuation_amount_adjustment, 
+						self.precision("item_tax_amount", item))
+				else:
+					item.item_tax_amount = flt(item_proportion * total_valuation_amount, 
+						self.precision("item_tax_amount", item))
+					valuation_amount_adjustment -= item.item_tax_amount
 
 				self.round_floats_in(item)
 				
diff --git a/manufacturing/doctype/production_order/test_production_order.py b/manufacturing/doctype/production_order/test_production_order.py
index ca28708..da45a9b 100644
--- a/manufacturing/doctype/production_order/test_production_order.py
+++ b/manufacturing/doctype/production_order/test_production_order.py
@@ -35,6 +35,7 @@
 		
 		stock_entry.doc.fg_completed_qty = 4
 		stock_entry.doc.posting_date = "2013-05-12"
+		stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
 		stock_entry.run_method("get_items")
 		stock_entry.submit()
 		
@@ -52,6 +53,7 @@
 		stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
 		stock_entry = webnotes.bean(stock_entry)
 		stock_entry.doc.posting_date = "2013-05-12"
+		stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
 		stock_entry.doc.fg_completed_qty = 15
 		stock_entry.run_method("get_items")
 		stock_entry.insert()
diff --git a/public/js/transaction.js b/public/js/transaction.js
index 0fe0535..1e03833 100644
--- a/public/js/transaction.js
+++ b/public/js/transaction.js
@@ -540,6 +540,14 @@
 	
 	calculate_taxes: function() {
 		var me = this;
+		var actual_tax_dict = {};
+
+		// maintain actual tax rate based on idx
+		$.each(this.frm.tax_doclist, function(i, tax) {
+			if (tax.charge_type == "Actual") {
+				actual_tax_dict[tax.idx] = flt(tax.rate);
+			}
+		});
 		
 		$.each(this.frm.item_doclist, function(n, item) {
 			var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
@@ -549,15 +557,15 @@
 				var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map);
 
 				me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
-				
-				// case when net total is 0 but there is an actual type charge
-				// in this case add the actual amount to tax.tax_amount
-				// and tax.grand_total_for_current_item for the first such iteration
-				if(tax.charge_type == "Actual" && 
-					!(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) {
-						var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax));
-						current_tax_amount += zero_net_total_adjustment;
+					
+				// Adjust divisional loss to the last item
+				if (tax.charge_type == "Actual") {
+					actual_tax_dict[tax.idx] -= current_tax_amount;
+					if (n == me.frm.item_doclist.length - 1) {
+						current_tax_amount += actual_tax_dict[tax.idx]
 					}
+				}
+
 				
 				// store tax_amount for current item as it will be used for
 				// charge type = 'On Previous Row Amount'
@@ -589,6 +597,11 @@
 				
 				// in tax.total, accumulate grand total for each item
 				tax.total += tax.grand_total_for_current_item;
+				
+				if (n == me.frm.item_doclist.length - 1) {
+					tax.total = flt(tax.total, precision("total", tax));
+					tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
+				}
 			});
 		});
 	},
diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py
index 85c20e8..f495f58 100644
--- a/selling/utils/__init__.py
+++ b/selling/utils/__init__.py
@@ -3,8 +3,8 @@
 
 from __future__ import unicode_literals
 import webnotes
-from webnotes import msgprint, _, throw
-from webnotes.utils import flt, cint, comma_and
+from webnotes import _, throw
+from webnotes.utils import flt, cint
 import json
 
 def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
@@ -121,10 +121,16 @@
 def _get_basic_details(args, item_bean, warehouse_fieldname):
 	item = item_bean.doc
 	
+	from webnotes.defaults import get_user_default_as_list
+	user_default_warehouse_list = get_user_default_as_list('warehouse')
+	user_default_warehouse = user_default_warehouse_list[0] \
+		if len(user_default_warehouse_list)==1 else ""
+	
 	out = webnotes._dict({
 			"item_code": item.name,
 			"description": item.description_html or item.description,
-			warehouse_fieldname: item.default_warehouse or args.get(warehouse_fieldname),
+			warehouse_fieldname: user_default_warehouse or item.default_warehouse \
+				or args.get(warehouse_fieldname),
 			"income_account": item.default_income_account or args.income_account \
 				or webnotes.conn.get_value("Company", args.company, "default_income_account"),
 			"expense_account": item.purchase_account or args.expense_account \