Merge pull request #1327 from akhileshdarjee/hotfix

Allow renaming of campaign
diff --git a/accounts/doctype/accounts_settings/accounts_settings.py b/accounts/doctype/accounts_settings/accounts_settings.py
index a6e9938..2475fda 100644
--- a/accounts/doctype/accounts_settings/accounts_settings.py
+++ b/accounts/doctype/accounts_settings/accounts_settings.py
@@ -6,6 +6,7 @@
 from __future__ import unicode_literals
 import webnotes
 from webnotes import _
+from webnotes.utils import cint
 
 class DocType:
 	def __init__(self, d, dl):
@@ -14,7 +15,12 @@
 	def on_update(self):
 		webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock)
 		
-		if self.doc.auto_accounting_for_stock:
+		if cint(self.doc.auto_accounting_for_stock):
+			# set default perpetual account in company
+			for company in webnotes.conn.sql("select name from tabCompany"):
+				webnotes.bean("Company", company[0]).save()
+			
+			# Create account head for warehouses
 			warehouse_list = webnotes.conn.sql("select name, company from tabWarehouse", as_dict=1)
 			warehouse_with_no_company = [d.name for d in warehouse_list if not d.company]
 			if warehouse_with_no_company:
diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py
index d3c6317..694917f 100644
--- a/accounts/doctype/gl_entry/gl_entry.py
+++ b/accounts/doctype/gl_entry/gl_entry.py
@@ -146,11 +146,12 @@
 		webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" %
 		 	(against_voucher_type, bal, against_voucher))
 			
-def validate_frozen_account(account, adv_adj):
+def validate_frozen_account(account, adv_adj=None):
 	frozen_account = webnotes.conn.get_value("Account", account, "freeze_account")
 	if frozen_account == 'Yes' and not adv_adj:
 		frozen_accounts_modifier = webnotes.conn.get_value( 'Accounts Settings', None, 
 			'frozen_accounts_modifier')
+		
 		if not frozen_accounts_modifier:
 			webnotes.throw(account + _(" is a frozen account. \
 				Either make the account active or assign role in Accounts Settings \
diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py
index 0b8ad46..fcd6846 100644
--- a/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -302,6 +302,7 @@
 		self.make_gl_entries()
 		self.update_against_document_in_jv()
 		self.update_prevdoc_status()
+		self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
 
 	def make_gl_entries(self):
 		auto_accounting_for_stock = \
@@ -358,7 +359,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({
@@ -420,7 +422,7 @@
 		remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher")
 		
 		self.update_prevdoc_status()
-		
+		self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
 		self.make_cancel_gl_entries()
 		
 	def on_update(self):
diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py
index bfba30f..a39702b 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/accounts/doctype/sales_invoice/sales_invoice.py
@@ -88,6 +88,7 @@
 		
 		self.update_status_updater_args()
 		self.update_prevdoc_status()
+		self.update_billing_status_for_zero_amount_refdoc("Sales Order")
 		
 		# this sequence because outstanding may get -ve
 		self.make_gl_entries()
@@ -114,6 +115,7 @@
 
 		self.update_status_updater_args()
 		self.update_prevdoc_status()
+		self.update_billing_status_for_zero_amount_refdoc("Sales Order")
 		
 		self.make_cancel_gl_entries()
 		
diff --git a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js
index b93f182..7f32e26 100644
--- a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js
+++ b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js
@@ -8,6 +8,7 @@
 			"label": wn._("Bank Account"),
 			"fieldtype": "Link",
 			"options": "Account",
+			"reqd": 1,
 			"get_query": function() {
 				return {
 					"query": "accounts.utils.get_account_list", 
@@ -22,7 +23,8 @@
 			"fieldname":"report_date",
 			"label": wn._("Date"),
 			"fieldtype": "Date",
-			"default": get_today()
+			"default": get_today(),
+			"reqd": 1
 		},
 	]
 }
\ No newline at end of file
diff --git a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index 431a649..5672497 100644
--- a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -3,13 +3,14 @@
 
 from __future__ import unicode_literals
 import webnotes
-from webnotes import _, msgprint
 from webnotes.utils import flt
 
 def execute(filters=None):
 	if not filters: filters = {}
-		
-	columns = get_columns()	
+	
+	debit_or_credit = webnotes.conn.get_value("Account", filters["account"], "debit_or_credit")
+	
+	columns = get_columns()
 	data = get_entries(filters)
 	
 	from accounts.utils import get_balance_on
@@ -20,47 +21,39 @@
 		total_debit += flt(d[4])
 		total_credit += flt(d[5])
 
-	if webnotes.conn.get_value("Account", filters["account"], "debit_or_credit") == 'Debit':
+	if debit_or_credit == 'Debit':
 		bank_bal = flt(balance_as_per_company) - flt(total_debit) + flt(total_credit)
 	else:
 		bank_bal = flt(balance_as_per_company) + flt(total_debit) - flt(total_credit)
 		
 	data += [
-		["", "", "", "Balance as per company books", balance_as_per_company, ""], 
+		get_balance_row("Balance as per company books", balance_as_per_company, debit_or_credit),
 		["", "", "", "Amounts not reflected in bank", total_debit, total_credit], 
-		["", "", "", "Balance as per bank", bank_bal, ""]
+		get_balance_row("Balance as per bank", bank_bal, debit_or_credit)
 	]
-			
-	return columns, data
 	
+	return columns, data
 	
 def get_columns():
 	return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100", 
 		"Clearance Date:Date:110", "Against Account:Link/Account:200", 
 		"Debit:Currency:120", "Credit:Currency:120"
 	]
-
-def get_conditions(filters):
-	conditions = ""
-	if not filters.get("account"):
-		msgprint(_("Please select Bank Account"), raise_exception=1)
-	else:
-		conditions += " and jvd.account = %(account)s"
-		
-	if not filters.get("report_date"):
-		msgprint(_("Please select Date on which you want to run the report"), raise_exception=1)
-	else:
-		conditions += """ and jv.posting_date <= %(report_date)s 
-			and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s"""
-
-	return conditions
 	
 def get_entries(filters):
-	conditions = get_conditions(filters)
-	entries = webnotes.conn.sql("""select jv.name, jv.posting_date, jv.clearance_date, 
-		jvd.against_account, jvd.debit, jvd.credit
-		from `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv 
-		where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= '' %s
-		order by jv.name DESC""" % conditions, filters, as_list=1)
+	entries = webnotes.conn.sql("""select 
+			jv.name, jv.posting_date, jv.clearance_date, jvd.against_account, jvd.debit, jvd.credit
+		from 
+			`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv 
+		where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= '' 
+			and jvd.account = %(account)s and jv.posting_date <= %(report_date)s 
+			and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
+		order by jv.name DESC""", filters, as_list=1)
 		
-	return entries
\ No newline at end of file
+	return entries
+	
+def get_balance_row(label, amount, debit_or_credit):
+	if debit_or_credit == "Debit":
+		return ["", "", "", label, amount, 0]
+	else:
+		return ["", "", "", label, 0, amount]
\ No newline at end of file
diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js
index 14b8279..e3957ab 100644
--- a/buying/doctype/purchase_common/purchase_common.js
+++ b/buying/doctype/purchase_common/purchase_common.js
@@ -302,11 +302,11 @@
 	
 	calculate_totals: function() {
 		var tax_count = this.frm.tax_doclist.length;
-		this.frm.doc.grand_total = flt(
-			tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
+		this.frm.doc.grand_total = flt(tax_count ? 
+			this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
 			precision("grand_total"));
-		this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
-			precision("grand_total_import"));
+		this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / 
+			this.frm.doc.conversion_rate, precision("grand_total_import"));
 			
 		this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
 			precision("total_tax"));
@@ -321,20 +321,26 @@
 		}
 		
 		// other charges added/deducted
+		this.frm.doc.other_charges_added = 0.0
+		this.frm.doc.other_charges_deducted = 0.0
 		if(tax_count) {
 			this.frm.doc.other_charges_added = wn.utils.sum($.map(this.frm.tax_doclist, 
-				function(tax) { return (tax.add_deduct_tax == "Add" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
+				function(tax) { return (tax.add_deduct_tax == "Add" 
+					&& in_list(["Valuation and Total", "Total"], tax.category)) ? 
+					tax.tax_amount : 0.0; }));
 		
 			this.frm.doc.other_charges_deducted = wn.utils.sum($.map(this.frm.tax_doclist, 
-				function(tax) { return (tax.add_deduct_tax == "Deduct" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
+				function(tax) { return (tax.add_deduct_tax == "Deduct" 
+					&& in_list(["Valuation and Total", "Total"], tax.category)) ? 
+					tax.tax_amount : 0.0; }));
 			
-			wn.model.round_floats_in(this.frm.doc, ["other_charges_added", "other_charges_deducted"]);
-			
-			this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added / this.frm.doc.conversion_rate,
-				precision("other_charges_added_import"));
-			this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted / this.frm.doc.conversion_rate,
-				precision("other_charges_deducted_import"));
+			wn.model.round_floats_in(this.frm.doc,
+				["other_charges_added", "other_charges_deducted"]);
 		}
+		this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added /
+			this.frm.doc.conversion_rate, precision("other_charges_added_import"));
+		this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted / 
+			this.frm.doc.conversion_rate, precision("other_charges_deducted_import"));
 	},
 	
 	_cleanup: function() {
diff --git a/config.json b/config.json
index 8499ee8..c252467 100644
--- a/config.json
+++ b/config.json
@@ -1,6 +1,6 @@
 {
  "app_name": "ERPNext", 
- "app_version": "3.5.1", 
+ "app_version": "3.6.2", 
  "base_template": "app/portal/templates/base.html", 
  "modules": {
   "Accounts": {
@@ -74,5 +74,5 @@
    "type": "module"
   }
  }, 
- "requires_framework_version": "==3.5.0"
+ "requires_framework_version": "==3.7.2"
 }
\ No newline at end of file
diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py
index a65bf26..e5b0b9d 100644
--- a/controllers/accounts_controller.py
+++ b/controllers/accounts_controller.py
@@ -3,7 +3,7 @@
 
 from __future__ import unicode_literals
 import webnotes
-from webnotes import _, msgprint, throw
+from webnotes import _, throw
 from webnotes.utils import flt, cint, today, cstr
 from webnotes.model.code import get_obj
 from setup.utils import get_company_currency
@@ -44,14 +44,13 @@
 	def validate_for_freezed_account(self):
 		for fieldname in ["customer", "supplier"]:
 			if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
-				accounts = webnotes.conn.get_values("Account", {"master_type": fieldname.title(), 
-					"master_name": self.doc.fields[fieldname], "company": self.doc.company}, 
-					"freeze_account", as_dict=1)
-				
+				accounts = webnotes.conn.get_values("Account", 
+					{"master_type": fieldname.title(), "master_name": self.doc.fields[fieldname], 
+					"company": self.doc.company}, "name")
 				if accounts:
-					if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts):
-						throw(_("Account for this ") + fieldname + _(" has been freezed. ") + 
-							self.doc.doctype + _(" can not be made."))
+					from accounts.doctype.gl_entry.gl_entry import validate_frozen_account
+					for account in accounts:						
+						validate_frozen_account(account[0])
 			
 	def set_price_list_currency(self, buying_or_selling):
 		if self.meta.get_field("currency"):
@@ -224,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'
@@ -249,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
 				
@@ -268,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..bdc7327 100644
--- a/controllers/buying_controller.py
+++ b/controllers/buying_controller.py
@@ -124,8 +124,8 @@
 		self.round_floats_in(self.doc, ["net_total", "net_total_import"])
 		
 	def calculate_totals(self):
-		self.doc.grand_total = flt(self.tax_doclist and \
-			self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total"))
+		self.doc.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist 
+			else self.doc.net_total, self.precision("grand_total"))
 		self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate,
 			self.precision("grand_total_import"))
 
@@ -137,6 +137,24 @@
 		
 		if self.meta.get_field("rounded_total_import"):
 			self.doc.rounded_total_import = _round(self.doc.grand_total_import)
+				
+		if self.meta.get_field("other_charges_added"):
+			self.doc.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist 
+				if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]), 
+				self.precision("other_charges_added"))
+				
+		if self.meta.get_field("other_charges_deducted"):
+			self.doc.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist 
+				if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]), 
+				self.precision("other_charges_deducted"))
+				
+		if self.meta.get_field("other_charges_added_import"):
+			self.doc.other_charges_added_import = flt(self.doc.other_charges_added / 
+				self.doc.conversion_rate, self.precision("other_charges_added_import"))
+				
+		if self.meta.get_field("other_charges_deducted_import"):
+			self.doc.other_charges_deducted_import = flt(self.doc.other_charges_deducted / 
+				self.doc.conversion_rate, self.precision("other_charges_deducted_import"))
 			
 	def calculate_outstanding_amount(self):
 		if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus < 2:
@@ -175,23 +193,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/controllers/selling_controller.py b/controllers/selling_controller.py
index 67c1462..4806c73 100644
--- a/controllers/selling_controller.py
+++ b/controllers/selling_controller.py
@@ -191,7 +191,8 @@
 			
 		self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
 			self.precision("other_charges_total"))
-		self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export,
+		self.doc.other_charges_total_export = flt(
+			self.doc.grand_total_export - self.doc.net_total_export,
 			self.precision("other_charges_total_export"))
 		
 		self.doc.rounded_total = _round(self.doc.grand_total)
diff --git a/controllers/status_updater.py b/controllers/status_updater.py
index a285c47..1743887 100644
--- a/controllers/status_updater.py
+++ b/controllers/status_updater.py
@@ -232,6 +232,43 @@
 								'Fully %(keyword)s', 'Partly %(keyword)s'))
 							where name='%(name)s'""" % args)
 							
+							
+	def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
+		ref_fieldname = ref_dt.lower().replace(" ", "_")
+		zero_amount_refdoc = []
+		all_zero_amount_refdoc = webnotes.conn.sql_list("""select name from `tab%s` 
+			where docstatus=1 and net_total = 0""" % ref_dt)
+	
+		for item in self.doclist.get({"parentfield": "entries"}):
+			if item.fields.get(ref_fieldname) \
+				and item.fields.get(ref_fieldname) in all_zero_amount_refdoc \
+				and item.fields.get(ref_fieldname) not in zero_amount_refdoc:
+					zero_amount_refdoc.append(item.fields[ref_fieldname])
+		
+		if zero_amount_refdoc:
+			self.update_biling_status(zero_amount_refdoc, ref_dt, ref_fieldname)
+	
+	def update_biling_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
+		for ref_dn in zero_amount_refdoc:
+			ref_doc_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) from `tab%s Item` 
+				where parent=%s""" % (ref_dt, '%s'), (ref_dn))[0][0])
+			
+			billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) 
+				from `tab%s Item` where %s=%s and docstatus=1""" % 
+				(self.doc.doctype, ref_fieldname, '%s'), (ref_dn))[0][0])
+			
+			per_billed = ((ref_doc_qty if billed_qty > ref_doc_qty else billed_qty)\
+				/ ref_doc_qty)*100
+			webnotes.conn.set_value(ref_dt, ref_dn, "per_billed", per_billed)
+			
+			from webnotes.model.meta import has_field
+			if has_field(ref_dt, "billing_status"):
+				if per_billed < 0.001: billing_status = "Not Billed"
+				elif per_billed >= 99.99: billing_status = "Fully Billed"
+				else: billing_status = "Partly Billed"
+			
+				webnotes.conn.set_value(ref_dt, ref_dn, "billing_status", billing_status)
+							
 def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None):
 	"""
 		Returns the tolerance for the item, if not set, returns global tolerance
diff --git a/hr/report/monthly_salary_register/monthly_salary_register.js b/hr/report/monthly_salary_register/monthly_salary_register.js
index 5d3abcc..32b4ef3 100644
--- a/hr/report/monthly_salary_register/monthly_salary_register.js
+++ b/hr/report/monthly_salary_register/monthly_salary_register.js
@@ -7,7 +7,7 @@
 			"fieldname":"month",
 			"label": wn._("Month"),
 			"fieldtype": "Select",
-			"options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
+			"options": "\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
 			"default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", 
 				"Dec"][wn.datetime.str_to_obj(wn.datetime.get_today()).getMonth()],
 		},
diff --git a/hr/report/monthly_salary_register/monthly_salary_register.py b/hr/report/monthly_salary_register/monthly_salary_register.py
index 8bd8f36..42c62e4 100644
--- a/hr/report/monthly_salary_register/monthly_salary_register.py
+++ b/hr/report/monthly_salary_register/monthly_salary_register.py
@@ -50,17 +50,17 @@
 		where ifnull(d_modified_amount, 0) != 0 and parent in (%s)""" % 
 		(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
 		
-	columns = columns + [(e + ":Link/Earning Type:120") for e in earning_types] + \
+	columns = columns + [(e + ":Currency:120") for e in earning_types] + \
 		["Arrear Amount:Currency:120", "Leave Encashment Amount:Currency:150", 
-		"Gross Pay:Currency:120"] + [(d + ":Link/Deduction Type:120") for d in ded_types] + \
+		"Gross Pay:Currency:120"] + [(d + ":Currency:120") for d in ded_types] + \
 		["Total Deduction:Currency:120", "Net Pay:Currency:120"]
 
 	return columns, earning_types, ded_types
 	
 def get_salary_slips(filters):
 	conditions, filters = get_conditions(filters)
-	salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s""" % 
-		conditions, filters, as_dict=1)
+	salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s
+		order by employee, month""" % conditions, filters, as_dict=1)
 	
 	if not salary_slips:
 		msgprint(_("No salary slip found for month: ") + cstr(filters.get("month")) + 
@@ -102,6 +102,6 @@
 	ss_ded_map = {}
 	for d in ss_deductions:
 		ss_ded_map.setdefault(d.parent, webnotes._dict()).setdefault(d.d_type, [])
-		ss_ded_map[d.parent][d.e_type] = flt(d.d_modified_amount)
+		ss_ded_map[d.parent][d.d_type] = flt(d.d_modified_amount)
 	
 	return ss_ded_map
\ No newline at end of file
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/patches/1401/p01_move_related_property_setters_to_custom_field.py b/patches/1401/p01_move_related_property_setters_to_custom_field.py
new file mode 100644
index 0000000..cf9221b
--- /dev/null
+++ b/patches/1401/p01_move_related_property_setters_to_custom_field.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import webnotes
+
+def execute():
+	webnotes.reload_doc("core", "doctype", "custom_field")
+	
+	cf_doclist = webnotes.get_doctype("Custom Field")
+
+	delete_list = []
+	for d in webnotes.conn.sql("""select cf.name as cf_name, ps.property, 
+			ps.value, ps.name as ps_name
+		from `tabProperty Setter` ps, `tabCustom Field` cf
+		where ps.doctype_or_field = 'DocField' and ps.property != 'previous_field'
+		and ps.doc_type=cf.dt and ps.field_name=cf.fieldname""", as_dict=1):
+			if cf_doclist.get_field(d.property):
+				webnotes.conn.sql("""update `tabCustom Field` 
+					set `%s`=%s where name=%s""" % (d.property, '%s', '%s'), (d.value, d.cf_name))
+				
+				delete_list.append(d.ps_name)
+	
+	if delete_list:
+		webnotes.conn.sql("""delete from `tabProperty Setter` where name in (%s)""" % 
+			', '.join(['%s']*len(delete_list)), tuple(delete_list))
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index d291d76..04a9288 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -263,5 +263,6 @@
 	"patches.1311.p08_email_digest_recipients",
 	"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
 	"patches.1312.p02_update_item_details_in_item_price",
+	"patches.1401.p01_move_related_property_setters_to_custom_field",
 	"patches.1401.p01_make_buying_selling_as_check_box_in_price_list",
 ]
\ No newline at end of file
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 \
diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py
index 12281b4..88d9dca 100644
--- a/setup/doctype/company/company.py
+++ b/setup/doctype/company/company.py
@@ -5,7 +5,7 @@
 import webnotes
 from webnotes import _, msgprint
 
-from webnotes.utils import cstr
+from webnotes.utils import cstr, cint
 import webnotes.defaults
 
 
@@ -237,21 +237,28 @@
 		account.insert()
 
 	def set_default_accounts(self):
-		accounts = {
+		def _set_default_accounts(accounts):
+			for a in accounts:
+				account_name = accounts[a] + " - " + self.doc.abbr
+				if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name):
+					webnotes.conn.set(self.doc, a, account_name)
+			
+		_set_default_accounts({
 			"default_income_account": "Sales",
 			"default_expense_account": "Cost of Goods Sold",
 			"receivables_group": "Accounts Receivable",
 			"payables_group": "Accounts Payable",
-			"default_cash_account": "Cash",
-			"stock_received_but_not_billed": "Stock Received But Not Billed",
-			"stock_adjustment_account": "Stock Adjustment",
-			"expenses_included_in_valuation": "Expenses Included In Valuation"
-		}
+			"default_cash_account": "Cash"
+		})
 		
-		for a in accounts:
-			account_name = accounts[a] + " - " + self.doc.abbr
-			if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name):
-				webnotes.conn.set(self.doc, a, account_name)
+		if cint(webnotes.conn.get_value("Accounts Settings", None, "auto_accounting_for_stock")):
+			_set_default_accounts({
+				"stock_received_but_not_billed": "Stock Received But Not Billed",
+				"stock_adjustment_account": "Stock Adjustment",
+				"expenses_included_in_valuation": "Expenses Included In Valuation"
+			})
+		
+		
 
 	def create_default_cost_center(self):
 		cc_list = [
diff --git a/startup/event_handlers.py b/startup/event_handlers.py
index f0323ea..b04b588 100644
--- a/startup/event_handlers.py
+++ b/startup/event_handlers.py
@@ -70,6 +70,6 @@
 
 def comment_added(doc):
 	"""add comment to feed"""
-	home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, doc.comment_by,
-		'<i>"' + doc.comment + '"</i>', '#6B24B3')
+	home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, 
+		doc.comment_by or doc.owner, '<i>"' + doc.comment + '"</i>', '#6B24B3')
 	
diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js
index c9aa75e..e18a0f2 100644
--- a/stock/doctype/item/item.js
+++ b/stock/doctype/item/item.js
@@ -29,10 +29,7 @@
 
 cur_frm.cscript.edit_prices_button = function() {
 	cur_frm.add_custom_button("Add / Edit Prices", function() {
-		wn.route_options = {
-			"item_code": cur_frm.doc.name
-		};
-		wn.set_route("Report", "Item Price");
+		wn.set_route("Report", "Item Price", {"item_code": cur_frm.doc.name});
 	}, "icon-money");
 }
 
diff --git a/support/doctype/customer_issue/customer_issue.txt b/support/doctype/customer_issue/customer_issue.txt
index f9fbc6b..76d49a8 100644
--- a/support/doctype/customer_issue/customer_issue.txt
+++ b/support/doctype/customer_issue/customer_issue.txt
@@ -2,11 +2,12 @@
  {
   "creation": "2013-01-10 16:34:30", 
   "docstatus": 0, 
-  "modified": "2013-11-02 16:59:22", 
+  "modified": "2014-01-14 15:56:22", 
   "modified_by": "Administrator", 
   "owner": "harshada@webnotestech.com"
  }, 
  {
+  "allow_import": 1, 
   "autoname": "naming_series:", 
   "doctype": "DocType", 
   "icon": "icon-bug", 
diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py
index 5c28d8d..f783faa 100644
--- a/utilities/transaction_base.py
+++ b/utilities/transaction_base.py
@@ -79,9 +79,10 @@
 		"""
 		customer_defaults = self.get_customer_defaults()
 					
-		customer_defaults["selling_price_list"] = customer_defaults.get("price_list") or \
-			webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or \
-			self.doc.selling_price_list
+		customer_defaults["selling_price_list"] = self.get_user_default_price_list("Selling") or \
+			customer_defaults.get("price_list") or \
+			webnotes.conn.get_value("Customer Group", self.doc.customer_group, 
+				"default_price_list") or self.doc.selling_price_list
 			
 		for fieldname, val in customer_defaults.items():
 			if self.meta.get_field(fieldname):
@@ -90,6 +91,12 @@
 		if self.meta.get_field("sales_team") and self.doc.customer:
 			self.set_sales_team_for_customer()
 			
+	def get_user_default_price_list(self, price_list_for):
+		from webnotes.defaults import get_user_default_as_list
+		user_default_price_list = get_user_default_as_list("selling_price_list" 
+			if price_list_for=="Selling" else "buying_price_list")
+		return user_default_price_list[0] if len(user_default_price_list)==1 else ""
+			
 	def set_sales_team_for_customer(self):
 		from webnotes.model import default_fields
 		
@@ -120,8 +127,9 @@
 		out["supplier_name"] = supplier.supplier_name
 		if supplier.default_currency:
 			out["currency"] = supplier.default_currency
-		if supplier.default_price_list:
-			out["buying_price_list"] = supplier.default_price_list
+			
+		out["buying_price_list"] = self.get_user_default_price_list("Buying") or \
+			supplier.default_price_list or self.doc.buying_price_list
 		
 		return out