gl_entry_map for journal voucher
diff --git a/accounts/doctype/journal_voucher/journal_voucher.py b/accounts/doctype/journal_voucher/journal_voucher.py
index 551b07d..a29ec79 100644
--- a/accounts/doctype/journal_voucher/journal_voucher.py
+++ b/accounts/doctype/journal_voucher/journal_voucher.py
@@ -24,10 +24,9 @@
 from webnotes import msgprint
 from setup.utils import get_company_currency
 
-sql = webnotes.conn.sql
-	
+from controllers.accounts_controller import AccountsController
 
-class DocType:
+class DocType(AccountsController):
 	def __init__(self,d,dl):
 		self.doc, self.doclist = d,dl
 		self.master_type = {}
@@ -37,74 +36,160 @@
 
 	def autoname(self):
 		if not self.doc.naming_series:
-			webnotes.msgprint("""Naming Series is mandatory""", raise_exception=1)
-			
+			webnotes.msgprint("""Naming Series is mandatory""", raise_exception=1)	
 		self.doc.name = make_autoname(self.doc.naming_series+'.#####')
+		
+	def validate(self):
+		if not self.doc.is_opening:
+			self.doc.is_opening='No'
+			
+		self.validate_debit_credit()
+		self.validate_cheque_info()
+		self.validate_entries_for_advance()
+		self.validate_against_jv()
+		get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year, \
+			self.doc.posting_date, 'Posting Date')
+		
+		self.set_against_account()
+		self.create_remarks()		
+		self.set_aging_date()
+		self.set_print_format_fields()
 
-	def get_outstanding(self, args):
-		args = eval(args)
-		o_s = sql("select outstanding_amount from `tab%s` where name = '%s'" % (args['doctype'],args['docname']))
-		if args['doctype'] == 'Purchase Invoice':
-			return {'debit': o_s and flt(o_s[0][0]) or 0}
-		if args['doctype'] == 'Sales Invoice':
-			return {'credit': o_s and flt(o_s[0][0]) or 0}
+	
+	def on_submit(self):
+		if self.doc.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
+			self.check_credit_days()
+		self.check_account_against_entries()
+		self.make_gl_entries()
+
+	def on_cancel(self):
+		self.make_gl_entries(cancel=1)
+
+	def validate_debit_credit(self):
+		for d in getlist(self.doclist, 'entries'):
+			if d.debit and d.credit:
+				msgprint("You cannot credit and debit same account at the same time.", 
+				 	raise_exception=1)
+
+	def validate_cheque_info(self):
+		if self.doc.voucher_type in ['Bank Voucher']:
+			if not self.doc.cheque_no or not self.doc.cheque_date:
+				msgprint("Reference No & Reference Date is required for %s" %
+				self.doc.voucher_type, raise_exception=1)
+				
+		if self.doc.cheque_date and not self.doc.cheque_no:
+			msgprint("Reference No is mandatory if you entered Reference Date", raise_exception=1)
+
+	def validate_entries_for_advance(self):
+		for d in getlist(self.doclist,'entries'):
+			if not d.is_advance and not d.against_voucher and \
+					not d.against_invoice and not d.against_jv:
+				master_type = webnotes.conn.get_value("Account", d.account, "master_type")
+				if (master_type == 'Customer' and flt(d.credit) > 0) or \
+						(master_type == 'Supplier' and flt(d.debit) > 0):
+					msgprint("Message: Please check Is Advance as 'Yes' against \
+						Account %s if this is an advance entry." % d.account)
+
+	def validate_against_jv(self):
+		for d in getlist(self.doclist, 'entries'):
+			if d.against_jv:
+				if d.against_jv == self.doc.name:
+					msgprint("You can not enter current voucher in 'Against JV' column",
+						raise_exception=1)
+				elif not webnotes.conn.sql("""select name from `tabJournal Voucher Detail` 
+						where account = '%s' and docstatus = 1 and parent = '%s'""" % 
+						(d.account, d.against_jv)):
+					msgprint("Against JV: %s is not valid." % d.against_jv, raise_exception=1)
+		
+	def set_against_account(self):
+		# Debit = Credit
+		debit, credit = 0.0, 0.0
+		debit_list, credit_list = [], []
+		for d in getlist(self.doclist, 'entries'):
+			debit += flt(d.debit)
+			credit += flt(d.credit)
+			if flt(d.debit)>0 and (d.account not in debit_list): debit_list.append(d.account)
+			if flt(d.credit)>0 and (d.account not in credit_list): credit_list.append(d.account)
+
+		self.doc.total_debit = debit
+		self.doc.total_credit = credit
+
+		if abs(self.doc.total_debit-self.doc.total_credit) > 0.001:
+			msgprint("Debit must be equal to Credit. The difference is %s" % 
+			 	(self.doc.total_debit-self.doc.total_credit), raise_exception=1)
+		
+		# update against account
+		for d in getlist(self.doclist, 'entries'):
+			if flt(d.debit) > 0: d.against_account = ', '.join(credit_list)
+			if flt(d.credit) > 0: d.against_account = ', '.join(debit_list)
 
 	def create_remarks(self):
 		r = []
 		if self.doc.cheque_no :
 			if self.doc.cheque_date:
-				r.append('Via Reference #%s dated %s' % (self.doc.cheque_no, formatdate(self.doc.cheque_date)))
+				r.append('Via Reference #%s dated %s' % 
+					(self.doc.cheque_no, formatdate(self.doc.cheque_date)))
 			else :
-				msgprint("Please enter Reference date")
-				raise Exception
+				msgprint("Please enter Reference date", raise_exception=1)
 		
 		for d in getlist(self.doclist, 'entries'):
 			if d.against_invoice and d.credit:
-				currency = sql("select currency from `tabSales Invoice` where name = '%s'" % d.against_invoice)
-				currency = currency and currency[0][0] or ''
-				r.append('%s %s against Invoice: %s' % (cstr(currency), fmt_money(flt(d.credit)), d.against_invoice))
+				currency = webnotes.conn.get_value("Sales Invoice", d.against_invoice, "currency")
+				r.append('%s %s against Invoice: %s' % 
+					(cstr(currency), fmt_money(flt(d.credit)), d.against_invoice))
+					
 			if d.against_voucher and d.debit:
-				bill_no = sql("select bill_no, bill_date, currency from `tabPurchase Invoice` where name=%s", d.against_voucher)
-				if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() not in ['na', 'not applicable', 'none']:
+				bill_no = webnotes.conn.sql("""select bill_no, bill_date, currency 
+					from `tabPurchase Invoice` where name=%s""", d.against_voucher)
+				if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
+						not in ['na', 'not applicable', 'none']:
 					bill_no = bill_no and bill_no[0]
-					r.append('%s %s against Bill %s dated %s' % (bill_no[2] and cstr(bill_no[2]) or '', fmt_money(flt(d.debit)), bill_no[0], bill_no[1] and formatdate(bill_no[1].strftime('%Y-%m-%d')) or ''))
+					r.append('%s %s against Bill %s dated %s' % 
+						(cstr(bill_no[0][2]), fmt_money(flt(d.debit)), bill_no[0][0], 
+						bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d')) or ''))
 	
 		if self.doc.user_remark:
 			r.append("User Remark : %s"%self.doc.user_remark)
 
 		if r:
 			self.doc.remark = ("\n").join(r)
-	
-	def get_authorized_user(self):
-		if self.is_approving_authority==-1:
-			self.is_approving_authority = 0
 
-			# Fetch credit controller role
-			approving_authority = sql("select value from `tabSingles` where field='credit_controller' and doctype='Global Defaults'")
-			approving_authority = approving_authority and approving_authority[0][0] or ''
-			
-			# Check logged-in user is authorized
-			if approving_authority in webnotes.user.get_roles():
-				self.is_approving_authority = 1
-				
-		return self.is_approving_authority
-			
-	def get_master_type(self, ac):
-		if not self.master_type.get(ac):
-			self.master_type[ac] = sql("select master_type from `tabAccount` where name=%s", ac)[0][0] or 'None'
-		return self.master_type[ac]
-	
-	def get_credit_days_for(self, ac):
-		if not self.credit_days_for.has_key(ac):
-			self.credit_days_for[ac] = sql("select credit_days from `tabAccount` where name='%s'" % ac)[0][0] or 0
-
-		if not self.credit_days_for[ac]:
-			if self.credit_days_global==-1:
-				self.credit_days_global = sql("select credit_days from `tabCompany` where name='%s'" % self.doc.company)[0][0] or 0
-			return self.credit_days_global
+	def set_aging_date(self):
+		if self.doc.is_opening != 'Yes':
+			self.doc.aging_date = self.doc.posting_date
 		else:
-			return self.credit_days_for[ac]
-	
+			# check account type whether supplier or customer
+			exists = False
+			for d in getlist(self.doclist, 'entries'):
+				account_type = webnotes.conn.get_value("Account", d.account, "account_type")
+				if account_type in ["Supplier", "Customer"]:
+					exists = True
+					break
+
+			# If customer/supplier account, aging date is mandatory
+			if exists and not self.doc.aging_date: 
+				msgprint("Aging Date is mandatory for opening entry", raise_exception=1)
+			else:
+				self.doc.aging_date = self.doc.posting_date
+
+	def set_print_format_fields(self):
+		for d in getlist(self.doclist, 'entries'):
+			account_type, master_type = webnotes.conn.get_value("Account", d.account, 
+				["account_type", "master_type"])
+				
+			if master_type in ['Supplier', 'Customer']:
+				if not self.doc.pay_to_recd_from:
+					self.doc.pay_to_recd_from = webnotes.conn.get_value(master_type, 
+						' - '.join(d.account.split(' - ')[:-1]), 
+						master_type == 'Customer' and 'customer_name' or 'supplier_name')
+			
+			if account_type == 'Bank or Cash':
+				company_currency = get_company_currency(self.doc.company)
+				amt = flt(d.debit) and d.debit or d.credit	
+				self.doc.total_amount = company_currency +' '+ cstr(amt)
+				from webnotes.utils import money_in_words
+				self.doc.total_amount_in_words = money_in_words(amt, company_currency)
+
 	def check_credit_days(self):
 		date_diff = 0
 		if self.doc.cheque_date:
@@ -113,48 +198,82 @@
 		if date_diff <= 0: return
 		
 		# Get List of Customer Account
-		acc_list = filter(lambda d: self.get_master_type(d.account)=='Customer', getlist(self.doclist,'entries'))
+		acc_list = filter(lambda d: webnotes.conn.get_value("Account", d.account, 
+		 	"master_type")=='Customer', getlist(self.doclist,'entries'))
 		
 		for d in acc_list:
 			credit_days = self.get_credit_days_for(d.account)
-			
 			# Check credit days
 			if credit_days > 0 and not self.get_authorized_user() and cint(date_diff) > credit_days:
-				msgprint("Credit Not Allowed: Cannot allow a check that is dated more than %s days after the posting date" % credit_days)
-				raise Exception
+				msgprint("Credit Not Allowed: Cannot allow a check that is dated \
+					more than %s days after the posting date" % credit_days, raise_exception=1)
 					
-	def check_account_against_entries(self):
-		for d in getlist(self.doclist,'entries'):
-			if d.against_invoice:
-				acc=sql("select debit_to from `tabSales Invoice` where name='%s'"%d.against_invoice)
-				if acc and acc[0][0] != d.account:
-					msgprint("Debit account is not matching with receivable voucher")
-					raise Exception
-			
-			if d.against_voucher:
-				acc=sql("select credit_to from `tabPurchase Invoice` where name='%s'"%d.against_voucher)
-				if acc and acc[0][0] != d.account:
-					msgprint("Credit account is not matching with payable voucher")
-					raise Exception
-					
-	def validate_cheque_info(self):
-		if self.doc.voucher_type in ['Bank Voucher']:
-			if not self.doc.cheque_no or not self.doc.cheque_date:
-				msgprint("Reference No & Reference Date is required for " + cstr(self.doc.voucher_type))
-				raise Exception
-				
-		if self.doc.cheque_date and not self.doc.cheque_no:
-			msgprint("Reference No is mandatory if you entered Reference Date")
-			raise Exception
-			
-	def validate_entries_for_advance(self):
-		for d in getlist(self.doclist,'entries'):
-			if not d.is_advance and not d.against_voucher and not d.against_invoice and not d.against_jv:
-				master_type = self.get_master_type(d.account)
-				if (master_type == 'Customer' and flt(d.credit) > 0) or (master_type == 'Supplier' and flt(d.debit) > 0):
-					msgprint("Message: Please check Is Advance as 'Yes' against Account %s if this is an advance entry." % d.account)
-				
+	def get_credit_days_for(self, ac):
+		if not self.credit_days_for.has_key(ac):
+			self.credit_days_for[ac] = cint(webnotes.conn.get_value("Account", ac, "credit_days"))
 
+		if not self.credit_days_for[ac]:
+			if self.credit_days_global==-1:
+				self.credit_days_global = cint(webnotes.conn.get_value("Company", 
+					self.doc.company, "credit_days"))
+					
+			return self.credit_days_global
+		else:
+			return self.credit_days_for[ac]
+
+	def get_authorized_user(self):
+		if self.is_approving_authority==-1:
+			self.is_approving_authority = 0
+
+			# Fetch credit controller role
+			approving_authority = webnotes.conn.get_value("Global Defaults", None, 
+				"credit_controller")
+			
+			# Check logged-in user is authorized
+			if approving_authority in webnotes.user.get_roles():
+				self.is_approving_authority = 1
+				
+		return self.is_approving_authority
+
+	def check_account_against_entries(self):
+		for d in self.doclist.get({"parentfield": "entries"}):
+			if d.against_invoice and webnotes.conn.get_value("Sales Invoice", 
+					d.against_invoice, "credit_to") != d.account:
+				msgprint("Debit account is not matching with Sales Invoice", raise_exception=1)
+			
+			if d.against_voucher and webnotes.conn.get_value("Purchase Invoice", 
+						d.against_voucher, "debit_to") != d.account:
+				msgprint("Credit account is not matching with Purchase Invoice", raise_exception=1)
+
+	def make_gl_entries(self, cancel=0):
+		gl_entries = []
+		for d in self.doclist.get({"parentfield": "entries"}):
+			gl_entries.append(
+				self.get_gl_dict({
+					"account": d.account,
+					"against": d.against_account,
+					"debit": d.debit,
+					"credit": d.credit,
+					"against_voucher_type": ((d.against_voucher and "Purchase Invoice") 
+						or (d.against_invoice and "Sales Invoice") 
+						or (d.against_jv and "Journal Voucher")),
+					"against_voucher": d.against_voucher or d.against_invoice or d.against_jv,
+					"remarks": self.doc.remark,
+					"cost_center": d.cost_center
+				}, cancel)
+			)
+			
+		super(DocType, self).make_gl_entries(cancel=cancel, gl_map=gl_entries)
+
+	def get_outstanding(self, args):
+		args = eval(args)
+		o_s = webnotes.conn.sql("""select outstanding_amount from `tab%s` where name = %s""" % 
+			(args['doctype'], '%s'), args['docname'])
+		if args['doctype'] == 'Purchase Invoice':
+			return {'debit': o_s and flt(o_s[0][0]) or 0}
+		if args['doctype'] == 'Sales Invoice':
+			return {'credit': o_s and flt(o_s[0][0]) or 0}
+	
 	def get_balance(self):
 		if not getlist(self.doclist,'entries'):
 			msgprint("Please enter atleast 1 entry in 'GL Entries' table")
@@ -164,7 +283,7 @@
 			
 			# If any row without amount, set the diff on that row
 			for d in getlist(self.doclist,'entries'):
-				if (d.credit==0 or d.credit is None) and (d.debit==0 or d.debit is None) and (flt(diff) != 0):
+				if not d.credit and not d.debit and flt(diff) != 0:
 					if diff>0:
 						d.credit = flt(diff)
 					elif diff<0:
@@ -185,71 +304,6 @@
 				self.doc.total_credit += flt(d.credit)
 
 			self.doc.difference = flt(self.doc.total_debit) - flt(self.doc.total_credit)
-			
-	def get_against_account(self):
-		# Debit = Credit
-		debit, credit = 0.0, 0.0
-		debit_list, credit_list = [], []
-		for d in getlist(self.doclist, 'entries'):
-			debit += flt(d.debit)
-			credit += flt(d.credit)
-			if flt(d.debit)>0 and (d.account not in debit_list): debit_list.append(d.account)
-			if flt(d.credit)>0 and (d.account not in credit_list): credit_list.append(d.account)
-
-		self.doc.total_debit = debit
-		self.doc.total_credit = credit
-
-		if abs(self.doc.total_debit-self.doc.total_credit) > 0.001:
-			msgprint("Debit must be equal to Credit. The difference is %s" % (self.doc.total_debit-self.doc.total_credit))
-			raise Exception
-		
-		# update against account
-		for d in getlist(self.doclist, 'entries'):
-			if flt(d.debit) > 0: d.against_account = ', '.join(credit_list)
-			if flt(d.credit) > 0: d.against_account = ', '.join(debit_list)
-
-	def set_aging_date(self):
-		if self.doc.is_opening != 'Yes':
-			self.doc.aging_date = self.doc.posting_date
-		else:
-			# check account type whether supplier or customer
-			exists = ''
-			for d in getlist(self.doclist, 'entries'):
-				exists = sql("select name from tabAccount where account_type in ('Supplier', 'Customer') and name = '%s'" % d.account)
-				if exists:
-					break
-
-			# If cus/supp aging dt is mandatory
-			if exists and not self.doc.aging_date: 
-				msgprint("Aging Date is mandatory for opening entry")
-				raise Exception
-			# otherwise aging dt = posting dt
-			else:
-				self.doc.aging_date = self.doc.posting_date
-
-	def set_print_format_fields(self):
-		for d in getlist(self.doclist, 'entries'):
-			#msgprint(self.doc.company)
-			chk_type = sql("select master_type, account_type from `tabAccount` where name='%s'" % d.account)
-			master_type, acc_type = chk_type and cstr(chk_type[0][0]) or '', chk_type and cstr(chk_type[0][1]) or ''
-			if master_type in ['Supplier', 'Customer']:
-				if not self.doc.pay_to_recd_from:
-					self.doc.pay_to_recd_from = webnotes.conn.get_value(master_type, ' - '.join(d.account.split(' - ')[:-1]), master_type == 'Customer' and 'customer_name' or 'supplier_name')
-			
-			if acc_type == 'Bank or Cash':
-				company_currency = get_company_currency(self.doc.company)
-				amt = flt(d.debit) and d.debit or d.credit	
-				self.doc.total_amount = company_currency +' '+ cstr(amt)
-				from webnotes.utils import money_in_words
-				self.doc.total_amount_in_words = money_in_words(amt, company_currency)
-				
-	def get_values(self):
-		cond = (flt(self.doc.write_off_amount) > 0) and ' and outstanding_amount <= '+self.doc.write_off_amount or ''
-		if self.doc.write_off_based_on == 'Accounts Receivable':
-			return sql("select name, debit_to, outstanding_amount from `tabSales Invoice` where docstatus = 1 and company = '%s' and outstanding_amount > 0 %s" % (self.doc.company, cond))
-		elif self.doc.write_off_based_on == 'Accounts Payable':
-			return sql("select name, credit_to, outstanding_amount from `tabPurchase Invoice` where docstatus = 1 and company = '%s' and outstanding_amount > 0 %s" % (self.doc.company, cond))
-
 
 	def get_outstanding_invoices(self):
 		self.doclist = self.doc.clear_table(self.doclist, 'entries')
@@ -272,48 +326,14 @@
 			jd.credit = total
 		jd.save(1)
 
-	def validate(self):
-		if not self.doc.is_opening:
-			self.doc.is_opening='No'
-		self.validate_debit_credit()
-		self.get_against_account()
-		self.validate_cheque_info()
-		self.create_remarks()
-		
-		self.validate_entries_for_advance()
-		self.set_aging_date()
-		
-		self.validate_against_jv()
-		self.set_print_format_fields()
-
-		#FY and Date validation
-		get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year, \
-			self.doc.posting_date, 'Posting Date')
-
-	def validate_debit_credit(self):
-		for d in getlist(self.doclist, 'entries'):
-			if d.debit and d.credit:
-				msgprint("You cannot credit and debit same account at the same time.", 
-				 	raise_exception=1)
-
-	def on_update(self):
-		pass
-				
-	def on_submit(self):
-		if self.doc.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
-			self.check_credit_days()
-		self.check_account_against_entries()
-		get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist)
-
-	def validate_against_jv(self):
-		for d in getlist(self.doclist, 'entries'):
-			if d.against_jv:
-				if d.against_jv == self.doc.name:
-					msgprint("You can not enter current voucher in 'Against JV' column")
-					raise Exception
-				elif not sql("select name from `tabJournal Voucher Detail` where account = '%s' and docstatus = 1 and parent = '%s'" % (d.account, d.against_jv)):
-					msgprint("Against JV: "+ d.against_jv + " is not valid. Please check")
-					raise Exception
-	
-	def on_cancel(self):
-		get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist, cancel=1)
\ No newline at end of file
+	def get_values(self):
+		cond = (flt(self.doc.write_off_amount) > 0) and \
+			' and outstanding_amount <= '+ self.doc.write_off_amount or ''
+		if self.doc.write_off_based_on == 'Accounts Receivable':
+			return webnotes.conn.sql("""select name, debit_to, outstanding_amount 
+				from `tabSales Invoice` where docstatus = 1 and company = %s 
+				and outstanding_amount > 0 %s""" % ('%s', cond), self.doc.company)
+		elif self.doc.write_off_based_on == 'Accounts Payable':
+			return webnotes.conn.sql("""select name, credit_to, outstanding_amount 
+				from `tabPurchase Invoice` where docstatus = 1 and company = %s 
+				and outstanding_amount > 0 %s""" % ('%s', cond), self.doc.company)
\ No newline at end of file
diff --git a/accounts/doctype/journal_voucher/test_journal_voucher.py b/accounts/doctype/journal_voucher/test_journal_voucher.py
index e043e9f..4c72092 100644
--- a/accounts/doctype/journal_voucher/test_journal_voucher.py
+++ b/accounts/doctype/journal_voucher/test_journal_voucher.py
@@ -44,6 +44,14 @@
 		"is_pl_account": "No",
 		"group_or_ledger": "Ledger"
 	},
+	"test_cost_center": {
+		"doctype": "Cost Center",
+		"cost_center_name": "Test Cost Center",
+		"parent_cost_center": "Root - %s" % abbr,
+		"company_name": company,
+		"group_or_ledger": "Ledger",
+		"company_abbr": abbr
+	},
 	"journal_voucher": [
 		{
 			"doctype": "Journal Voucher",
@@ -59,7 +67,7 @@
 			"parentfield": "entries",
 			"account": "Test Expense - %s" % abbr,
 			"debit": 5000,
-			"cost_center": "Default CC Ledger - %s" % abbr,
+			"cost_center": "Test Cost Center - %s" % abbr,
 		},
 		{
 			"doctype": "Journal Voucher Detail",
@@ -80,6 +88,7 @@
 		# create a dummy account
 		webnotes.model.insert([data["expense_account"]])
 		webnotes.model.insert([data["supplier_account"]])
+		webnotes.model.insert([data["test_cost_center"]])
 		
 	def tearDown(self):
 		webnotes.conn.rollback()
diff --git a/accounts/utils/__init__.py b/accounts/utils/__init__.py
deleted file mode 100644
index 8ad1899..0000000
--- a/accounts/utils/__init__.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# ERPNext - web based ERP (http://erpnext.com)
-# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import unicode_literals
-
-import webnotes
-from webnotes.utils import nowdate
-
-class FiscalYearError(webnotes.ValidationError): pass
-
-def get_fiscal_year(date, verbose=1):
-	from webnotes.utils import formatdate
-	# if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate)
-	fy = webnotes.conn.sql("""select name, year_start_date, 
-		subdate(adddate(year_start_date, interval 1 year), interval 1 day) 
-			as year_end_date
-		from `tabFiscal Year`
-		where %s >= year_start_date and %s < adddate(year_start_date, interval 1 year)
-		order by year_start_date desc""", (date, date))
-	
-	if not fy:
-		error_msg = """%s not in any Fiscal Year""" % formatdate(date)
-		if verbose: webnotes.msgprint(error_msg)
-		raise FiscalYearError, error_msg
-	
-	return fy[0]
-
-@webnotes.whitelist()
-def get_balance_on(account=None, date=None):
-	if not account and webnotes.form_dict.get("account"):
-		account = webnotes.form_dict.get("account")
-		date = webnotes.form_dict.get("date")
-	
-	cond = []
-	if date:
-		cond.append("posting_date <= '%s'" % date)
-	else:
-		# get balance of all entries that exist
-		date = nowdate()
-		
-	try:
-		year_start_date = get_fiscal_year(date, verbose=0)[1]
-	except FiscalYearError, e:
-		from webnotes.utils import getdate
-		if getdate(date) > getdate(nowdate()):
-			# if fiscal year not found and the date is greater than today
-			# get fiscal year for today's date and its corresponding year start date
-			year_start_date = get_fiscal_year(nowdate(), verbose=1)[1]
-		else:
-			# this indicates that it is a date older than any existing fiscal year.
-			# hence, assuming balance as 0.0
-			return 0.0
-		
-	acc = webnotes.conn.get_value('Account', account, \
-		['lft', 'rgt', 'debit_or_credit', 'is_pl_account', 'group_or_ledger'], as_dict=1)
-	
-	# for pl accounts, get balance within a fiscal year
-	if acc.is_pl_account == 'Yes':
-		cond.append("posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" \
-			% year_start_date)
-	
-	# different filter for group and ledger - improved performance
-	if acc.group_or_ledger=="Group":
-		cond.append("""exists (
-			select * from `tabAccount` ac where ac.name = gle.account
-			and ac.lft >= %s and ac.rgt <= %s
-		)""" % (acc.lft, acc.rgt))
-	else:
-		cond.append("""gle.account = "%s" """ % (account, ))
-	
-	# join conditional conditions
-	cond = " and ".join(cond)
-	if cond:
-		cond += " and "
-	
-	bal = webnotes.conn.sql("""
-		SELECT sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) 
-		FROM `tabGL Entry` gle
-		WHERE %s ifnull(is_cancelled, 'No') = 'No' """ % (cond, ))[0][0]
-
-	# if credit account, it should calculate credit - debit
-	if bal and acc.debit_or_credit == 'Credit':
-		bal = -bal
-
-	# if bal is None, return 0
-	return bal or 0
\ No newline at end of file