[salary slip] total no. of working days calculation [issue] webnotes/erpnext#285
diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py
index e3e5d5e..0a2a20b 100644
--- a/controllers/accounts_controller.py
+++ b/controllers/accounts_controller.py
@@ -141,8 +141,9 @@
 					
 	def calculate_taxes_and_totals(self):
 		# validate conversion rate
-		if not self.doc.currency:
-			self.doc.currency = get_company_currency(self.doc.company)
+		company_currency = get_company_currency(self.doc.company)
+		if not self.doc.currency or self.doc.currency == company_currency:
+			self.doc.currency = company_currency
 			self.doc.conversion_rate = 1.0
 		else:
 			validate_conversion_rate(self.doc.currency, self.doc.conversion_rate,
diff --git a/hr/doctype/deduction_type/test_deduction_type.py b/hr/doctype/deduction_type/test_deduction_type.py
new file mode 100644
index 0000000..5960aac
--- /dev/null
+++ b/hr/doctype/deduction_type/test_deduction_type.py
@@ -0,0 +1,10 @@
+test_records = [
+	[{
+			"doctype": "Deduction Type",
+			"deduction_name": "_Test Professional Tax"
+	}],
+	[{
+			"doctype": "Deduction Type",
+			"deduction_name": "_Test TDS"
+	}]
+]
\ No newline at end of file
diff --git a/hr/doctype/earning_type/test_earning_type.py b/hr/doctype/earning_type/test_earning_type.py
new file mode 100644
index 0000000..ea245a2
--- /dev/null
+++ b/hr/doctype/earning_type/test_earning_type.py
@@ -0,0 +1,12 @@
+test_records = [
+	[{
+			"doctype": "Earning Type",
+			"earning_name": "_Test Basic Salary",
+			"taxable": "Yes"
+	}],
+	[{
+			"doctype": "Earning Type",
+			"earning_name": "_Test Allowance",
+			"taxable": "Yes"
+	}]
+]
\ No newline at end of file
diff --git a/hr/doctype/holiday_list/test_holiday_list.py b/hr/doctype/holiday_list/test_holiday_list.py
index e3a2d82..07b7fe5 100644
--- a/hr/doctype/holiday_list/test_holiday_list.py
+++ b/hr/doctype/holiday_list/test_holiday_list.py
@@ -1,7 +1,8 @@
 test_records = [[{
 		"doctype": "Holiday List",
 		"holiday_list_name": "_Test Holiday List",
-		"fiscal_year": "_Test Fiscal Year 2013"
+		"fiscal_year": "_Test Fiscal Year 2013",
+		"is_default": 1
 	}, {
 		"doctype": "Holiday",
 		"parent": "_Test Holiday List",
diff --git a/hr/doctype/hr_settings/__init__.py b/hr/doctype/hr_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hr/doctype/hr_settings/__init__.py
diff --git a/hr/doctype/hr_settings/hr_settings.py b/hr/doctype/hr_settings/hr_settings.py
new file mode 100644
index 0000000..928aa9f
--- /dev/null
+++ b/hr/doctype/hr_settings/hr_settings.py
@@ -0,0 +1,8 @@
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+class DocType:
+	def __init__(self, d, dl):
+		self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/hr/doctype/hr_settings/hr_settings.txt b/hr/doctype/hr_settings/hr_settings.txt
new file mode 100644
index 0000000..e3694d0
--- /dev/null
+++ b/hr/doctype/hr_settings/hr_settings.txt
@@ -0,0 +1,59 @@
+[
+ {
+  "creation": "2013-08-02 13:45:23", 
+  "docstatus": 0, 
+  "modified": "2013-08-02 14:22:26", 
+  "modified_by": "Administrator", 
+  "owner": "Administrator"
+ }, 
+ {
+  "doctype": "DocType", 
+  "document_type": "Other", 
+  "icon": "icon-cog", 
+  "issingle": 1, 
+  "module": "HR", 
+  "name": "__common__"
+ }, 
+ {
+  "doctype": "DocField", 
+  "name": "__common__", 
+  "parent": "HR Settings", 
+  "parentfield": "fields", 
+  "parenttype": "DocType", 
+  "permlevel": 0
+ }, 
+ {
+  "create": 1, 
+  "doctype": "DocPerm", 
+  "name": "__common__", 
+  "parent": "HR Settings", 
+  "parentfield": "permissions", 
+  "parenttype": "DocType", 
+  "permlevel": 0, 
+  "read": 1, 
+  "role": "System Manager", 
+  "write": 1
+ }, 
+ {
+  "doctype": "DocType", 
+  "name": "HR Settings"
+ }, 
+ {
+  "description": "Employee record is created using selected field. ", 
+  "doctype": "DocField", 
+  "fieldname": "emp_created_by", 
+  "fieldtype": "Select", 
+  "label": "Employee Records to be created by", 
+  "options": "Naming Series\nEmployee Number"
+ }, 
+ {
+  "description": "If checked, Total no. of Working Days will include holidays, and this will reduce the value of Salary Per Day", 
+  "doctype": "DocField", 
+  "fieldname": "include_holidays_in_total_working_days", 
+  "fieldtype": "Check", 
+  "label": "Include holidays in Total no. of Working Days"
+ }, 
+ {
+  "doctype": "DocPerm"
+ }
+]
\ No newline at end of file
diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py
index 338225c..4acabda 100644
--- a/hr/doctype/leave_application/test_leave_application.py
+++ b/hr/doctype/leave_application/test_leave_application.py
@@ -236,5 +236,15 @@
 		"fiscal_year": "_Test Fiscal Year 2013",
 		"employee": "_T-Employee-0002",
 		"company": "_Test Company"
+	}],
+	[{
+		"doctype": "Leave Application",
+		"leave_type": "_Test Leave Type LWP",
+		"from_date": "2013-01-02",
+		"to_date": "2013-01-02",
+		"posting_date": "2013-01-02",
+		"fiscal_year": "_Test Fiscal Year 2013",
+		"employee": "_T-Employee-0001",
+		"company": "_Test Company",
 	}]
 ]
diff --git a/hr/doctype/leave_type/test_leave_type.py b/hr/doctype/leave_type/test_leave_type.py
index 4d78975..9b3b240 100644
--- a/hr/doctype/leave_type/test_leave_type.py
+++ b/hr/doctype/leave_type/test_leave_type.py
@@ -2,5 +2,10 @@
 	[{
 		"leave_type_name": "_Test Leave Type",
 		"doctype": "Leave Type"
+	}],
+	[{
+		"leave_type_name": "_Test Leave Type LWP",
+		"doctype": "Leave Type",
+		"is_lwp": 1
 	}]
 ]
\ No newline at end of file
diff --git a/hr/doctype/salary_manager/salary_manager.py b/hr/doctype/salary_manager/salary_manager.py
index e9b3dd7..7a8f1da 100644
--- a/hr/doctype/salary_manager/salary_manager.py
+++ b/hr/doctype/salary_manager/salary_manager.py
@@ -112,26 +112,16 @@
 			if not sql("""select name from `tabSalary Slip` 
 					where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s
 					""", (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)):
-				ss = Document('Salary Slip')
-				ss.fiscal_year = self.doc.fiscal_year
-				ss.employee = emp[0]
-				ss.month = self.doc.month
-				ss.email_check = self.doc.send_email
-				ss.company = self.doc.company
-				ss.save(1)
-			
-				ss_obj = get_obj('Salary Slip', ss.name, with_children=1)
-				ss_obj.get_emp_and_leave_details()
-				ss_obj.calculate_net_pay()
-				ss_obj.validate()
-				ss_obj.doc.save()
-			
-				for d in getlist(ss_obj.doclist, 'earning_details'):
-					d.save()
-				for d in getlist(ss_obj.doclist, 'deduction_details'):
-					d.save()
-					
-				ss_list.append(ss.name)
+				ss = webnotes.bean({
+					"doctype": "Salary Slip",
+					"fiscal_year": self.doc.fiscal_year,
+					"employee": emp[0],
+					"month": self.doc.month,
+					"email_check": self.doc.send_email,
+					"company": self.doc.company,
+				})
+				ss.insert()
+				ss_list.append(ss.doc.name)
 		
 		return self.create_log(ss_list)
 	
diff --git a/hr/doctype/salary_slip/salary_slip.py b/hr/doctype/salary_slip/salary_slip.py
index 09bd602..3e943bc 100644
--- a/hr/doctype/salary_slip/salary_slip.py
+++ b/hr/doctype/salary_slip/salary_slip.py
@@ -61,7 +61,7 @@
 			["bank_name", "bank_ac_no", "esic_card_no", "pf_number"], as_dict=1)
 		if emp:
 			self.doc.bank_name = emp.bank_name
-			self.doc.bank_ac_no = emp.bank_ac_no
+			self.doc.bank_account_no = emp.bank_ac_no
 			self.doc.esic_no = emp.esic_card_no
 			self.doc.pf_no = emp.pf_number
 
@@ -72,9 +72,17 @@
 			self.doc.month = "%02d" % getdate(nowdate()).month
 			
 		m = get_obj('Salary Manager').get_month_details(self.doc.fiscal_year, self.doc.month)
+		holidays = self.get_holidays_for_employee(m)
 		
+		if not cint(webnotes.conn.get_value("HR Settings", "HR Settings",
+			"include_holidays_in_total_working_days")):
+				m["month_days"] -= len(holidays)
+				if m["month_days"] < 0:
+					msgprint(_("Bummer! There are more holidays than working days this month."),
+						raise_exception=True)
+			
 		if not lwp:
-			lwp = self.calculate_lwp(m)
+			lwp = self.calculate_lwp(holidays, m)
 		self.doc.total_days_in_month = m['month_days']
 		self.doc.leave_without_pay = lwp
 		payment_days = flt(self.get_payment_days(m)) - flt(lwp)
@@ -103,11 +111,8 @@
 				payment_days = 0
 
 		return payment_days
-
-
-
-
-	def calculate_lwp(self, m):
+		
+	def get_holidays_for_employee(self, m):
 		holidays = sql("""select t1.holiday_date 
 			from `tabHoliday` t1, tabEmployee t2 
 			where t1.parent = t2.holiday_list and t2.name = %s 
@@ -117,8 +122,13 @@
 			holidays = sql("""select t1.holiday_date 
 				from `tabHoliday` t1, `tabHoliday List` t2 
 				where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 
-				and t2.fiscal_year = %s""", self.doc.fiscal_year)
+				and t2.fiscal_year = %s
+				and t1.holiday_date between %s and %s""", (self.doc.fiscal_year, 
+					m['month_start_date'], m['month_end_date']))
 		holidays = [cstr(i[0]) for i in holidays]
+		return holidays
+
+	def calculate_lwp(self, holidays, m):
 		lwp = 0
 		for d in range(m['month_days']):
 			dt = add_days(cstr(m['month_start_date']), d)
@@ -133,7 +143,7 @@
 					and %s between from_date and to_date
 				""", (self.doc.employee, dt))
 				if leave:
-					lwp = cint(leave[0][1]) and lwp + 0.5 or lwp + 1
+					lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1)
 		return lwp
 
 	def check_existing(self):
@@ -150,17 +160,29 @@
 	def validate(self):
 		from webnotes.utils import money_in_words
 		self.check_existing()
+		
+		if not (len(self.doclist.get({"parentfield": "earning_details"})) or 
+			len(self.doclist.get({"parentfield": "deduction_details"}))):
+				self.get_emp_and_leave_details()
+		else:
+			self.get_leave_details(self.doc.leave_without_pay)
+
+		if not self.doc.net_pay:
+			self.calculate_net_pay()
+			
 		company_currency = get_company_currency(self.doc.company)
 		self.doc.total_in_words = money_in_words(self.doc.rounded_total, company_currency)
 
 	def calculate_earning_total(self):
 		self.doc.gross_pay = flt(self.doc.arrear_amount) + flt(self.doc.leave_encashment_amount)
-		for d in getlist(self.doclist, 'earning_details'):
+		for d in self.doclist.get({"parentfield": "earning_details"}):
 			if cint(d.e_depends_on_lwp) == 1:
 				d.e_modified_amount = round(flt(d.e_amount) * flt(self.doc.payment_days)
 					/ cint(self.doc.total_days_in_month), 2)
 			elif not self.doc.payment_days:
 				d.e_modified_amount = 0
+			else:
+				d.e_modified_amount = d.e_amount
 			self.doc.gross_pay += flt(d.e_modified_amount)
 	
 	def calculate_ded_total(self):
@@ -171,6 +193,8 @@
 					/ cint(self.doc.total_days_in_month), 2)
 			elif not self.doc.payment_days:
 				d.d_modified_amount = 0
+			else:
+				d.d_modified_amount = d.d_amount
 			
 			self.doc.total_deduction += flt(d.d_modified_amount)
 				
diff --git a/hr/doctype/salary_slip/salary_slip.txt b/hr/doctype/salary_slip/salary_slip.txt
index 871c6b8..641adae 100644
--- a/hr/doctype/salary_slip/salary_slip.txt
+++ b/hr/doctype/salary_slip/salary_slip.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-01-10 16:34:15", 
   "docstatus": 0, 
-  "modified": "2013-07-05 14:53:44", 
+  "modified": "2013-08-02 19:23:13", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -190,7 +190,7 @@
   "doctype": "DocField", 
   "fieldname": "total_days_in_month", 
   "fieldtype": "Data", 
-  "label": "Total days in month", 
+  "label": "Total Working Days In The Month", 
   "oldfieldname": "total_days_in_month", 
   "oldfieldtype": "Int", 
   "read_only": 1, 
@@ -208,7 +208,7 @@
   "doctype": "DocField", 
   "fieldname": "payment_days", 
   "fieldtype": "Float", 
-  "label": "Payment days", 
+  "label": "Payment Days", 
   "oldfieldname": "payment_days", 
   "oldfieldtype": "Float", 
   "read_only": 1, 
diff --git a/hr/doctype/salary_slip/test_salary_slip.py b/hr/doctype/salary_slip/test_salary_slip.py
new file mode 100644
index 0000000..e48bf62
--- /dev/null
+++ b/hr/doctype/salary_slip/test_salary_slip.py
@@ -0,0 +1,85 @@
+import webnotes
+import unittest
+
+class TestSalarySlip(unittest.TestCase):
+	def setUp(self):
+		webnotes.conn.sql("""delete from `tabLeave Application`""")
+		webnotes.conn.sql("""delete from `tabSalary Slip`""")
+		from hr.doctype.leave_application.test_leave_application import test_records as leave_applications
+		la = webnotes.bean(copy=leave_applications[4])
+		la.insert()
+		la.doc.status = "Approved"
+		la.submit()
+		
+	def tearDown(self):
+		webnotes.conn.set_value("HR Settings", "HR Settings", "include_holidays_in_total_working_days", 0)
+		
+	def test_salary_slip_with_holidays_included(self):
+		webnotes.conn.set_value("HR Settings", "HR Settings", "include_holidays_in_total_working_days", 1)
+		ss = webnotes.bean(copy=test_records[0])
+		ss.insert()
+		self.assertEquals(ss.doc.total_days_in_month, 31)
+		self.assertEquals(ss.doc.payment_days, 30)
+		self.assertEquals(ss.doclist[1].e_modified_amount, 14516.13)
+		self.assertEquals(ss.doclist[2].e_modified_amount, 500)
+		self.assertEquals(ss.doclist[3].d_modified_amount, 100)
+		self.assertEquals(ss.doclist[4].d_modified_amount, 48.39)
+		self.assertEquals(ss.doc.gross_pay, 15016.13)
+		self.assertEquals(ss.doc.net_pay, 14867.74)
+		
+	def test_salary_slip_with_holidays_excluded(self):
+		ss = webnotes.bean(copy=test_records[0])
+		ss.insert()
+		self.assertEquals(ss.doc.total_days_in_month, 30)
+		self.assertEquals(ss.doc.payment_days, 29)
+		self.assertEquals(ss.doclist[1].e_modified_amount, 14500)
+		self.assertEquals(ss.doclist[2].e_modified_amount, 500)
+		self.assertEquals(ss.doclist[3].d_modified_amount, 100)
+		self.assertEquals(ss.doclist[4].d_modified_amount, 48.33)
+		self.assertEquals(ss.doc.gross_pay, 15000)
+		self.assertEquals(ss.doc.net_pay, 14851.67)
+
+test_dependencies = ["Leave Application"]
+
+test_records = [
+	[
+		{
+			"doctype": "Salary Slip",
+			"employee": "_T-Employee-0001",
+			"employee_name": "_Test Employee",
+			"company": "_Test Company",
+			"fiscal_year": "_Test Fiscal Year 2013",
+			"month": "01",
+			"total_days_in_month": 31,
+			"payment_days": 31
+		},
+		{
+			"doctype": "Salary Slip Earning",
+			"parentfield": "earning_details",
+			"e_type": "_Test Basic Salary",
+			"e_amount": 15000,
+			"e_depends_on_lwp": 1
+		},
+		{
+			"doctype": "Salary Slip Earning",
+			"parentfield": "earning_details",
+			"e_type": "_Test Allowance",
+			"e_amount": 500,
+			"e_depends_on_lwp": 0
+		},
+		{
+			"doctype": "Salary Slip Deduction",
+			"parentfield": "deduction_details",
+			"d_type": "_Test Professional Tax",
+			"d_amount": 100,
+			"d_depends_on_lwp": 0
+		},
+		{
+			"doctype": "Salary Slip Deduction",
+			"parentfield": "deduction_details",
+			"d_type": "_Test TDS",
+			"d_amount": 50,
+			"d_depends_on_lwp": 1
+		},
+	]
+]
\ No newline at end of file
diff --git a/hr/page/hr_home/hr_home.js b/hr/page/hr_home/hr_home.js
index 21ec1e1..54c3d66 100644
--- a/hr/page/hr_home/hr_home.js
+++ b/hr/page/hr_home/hr_home.js
@@ -162,6 +162,18 @@
 		]
 	},
 	{
+		title: wn._("Setup"),
+		icon: "icon-cog",
+		items: [
+			{
+				"label": wn._("HR Settings"),
+				"route": "Form/HR Settings",
+				"doctype":"HR Settings",
+				"description": "Settings for HR Module"
+			}
+		]
+	},
+	{
 		title: wn._("Reports"),
 		right: true,
 		icon: "icon-list",
diff --git a/patches/august_2013/__init__.py b/patches/august_2013/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/patches/august_2013/__init__.py
diff --git a/patches/august_2013/p01_hr_settings.py b/patches/august_2013/p01_hr_settings.py
new file mode 100644
index 0000000..408f1e4
--- /dev/null
+++ b/patches/august_2013/p01_hr_settings.py
@@ -0,0 +1,16 @@
+import webnotes
+
+def execute():
+	webnotes.reload_doc("hr", "doctype", "hr_settings")
+	webnotes.reload_doc("setup", "doctype", "global_defaults")
+	
+	hr = webnotes.bean("HR Settings", "HR Settings")
+	hr.doc.emp_created_by = webnotes.conn.get_value("Global Defaults", "Global Defaults", "emp_created_by")
+	
+	if webnotes.conn.sql("""select name from `tabSalary Slip` where docstatus=1 limit 1"""):
+		hr.doc.include_holidays_in_total_working_days = 1
+	
+	hr.save()
+	
+	webnotes.conn.sql("""delete from `tabSingles` where doctype = 'Global Defaults' 
+		and field = 'emp_created_by'""")
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index 1426539..c4c4a83 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -264,4 +264,5 @@
 	"patches.july_2013.p10_change_partner_user_to_website_user",
 	"patches.july_2013.p11_update_price_list_currency",
 	"execute:webnotes.bean('Selling Settings').save() #2013-07-29",
+	"patches.august_2013.p01_hr_settings",
 ]
\ No newline at end of file
diff --git a/setup/doctype/global_defaults/global_defaults.txt b/setup/doctype/global_defaults/global_defaults.txt
index b59ca94..8f5b940 100644
--- a/setup/doctype/global_defaults/global_defaults.txt
+++ b/setup/doctype/global_defaults/global_defaults.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-05-02 17:53:24", 
   "docstatus": 0, 
-  "modified": "2013-07-15 15:03:01", 
+  "modified": "2013-08-02 13:45:12", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -182,15 +182,6 @@
   "read_only": 0
  }, 
  {
-  "description": "Employee record is created using selected field. ", 
-  "doctype": "DocField", 
-  "fieldname": "emp_created_by", 
-  "fieldtype": "Select", 
-  "label": "Employee Records to be created by ", 
-  "options": "Naming Series\nEmployee Number", 
-  "read_only": 0
- }, 
- {
   "doctype": "DocPerm"
  }
 ]
\ No newline at end of file