Merge branch 'develop' into jam_enterprise_emp_benefit
diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js
index 8cf6909..7859a47 100644
--- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js
+++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js
@@ -2,7 +2,55 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Employee Benefit Application', {
-	refresh: function(frm) {
-
+	setup: function(frm) {
+		frm.set_query("earning_component", "employee_benefits", function() {
+			return {
+				filters: {
+					type: "Earning",
+					is_flexible_benefit: true,
+					disabled: false
+				}
+			};
+		});
+	},
+	employee: function(frm) {
+		frappe.call({
+			method: "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits",
+			args:{
+				employee: frm.doc.employee,
+				on_date: frm.doc.date
+			},
+			callback: function (data) {
+				if(!data.exc){
+					if(data.message){
+						frm.set_value("max_benefits", data.message);
+					}
+				}
+			}
+		});
 	}
 });
+
+frappe.ui.form.on("Employee Benefit Application Detail",{
+	amount:  function(frm, cdt, cdn) {
+		calculate_all(frm.doc, cdt, cdn);
+	}
+});
+
+var calculate_all = function(doc, dt, dn) {
+	var tbl = doc.employee_benefits || [];
+	var pro_rata_dispensed_amount = 0;
+	var total_amount = 0;
+	for(var i = 0; i < tbl.length; i++){
+		if(cint(tbl[i].amount) > 0) {
+			total_amount += flt(tbl[i].amount);
+		}
+		if(tbl[i].is_pro_rata_applicable == 1){
+			pro_rata_dispensed_amount += flt(tbl[i].amount)
+		}
+	}
+	doc.total_amount = total_amount;
+	doc.remainig_benefits = doc.max_benefits - total_amount;
+	doc.pro_rata_dispensed_amount = pro_rata_dispensed_amount;
+	refresh_many(['pro_rata_dispensed_amount', 'total_amount','remainig_benefits']);
+};
diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json
index 0fff4fd..3c1c8aa 100644
--- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json
+++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json
@@ -83,6 +83,68 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "max_benefits", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Max Benefits (Yearly)", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "remainig_benefits", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Remainig Benefits (Yearly)", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "column_break_2", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -113,6 +175,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "default": "Today", 
+   "fieldname": "date", 
+   "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Date", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "payroll_period", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -145,6 +239,68 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "pro_rata_dispensed_amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Pro Rata Dispensed Amount", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "total_amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Total Amount", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "amended_from", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -243,7 +399,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-04-14 15:35:20.748301", 
+ "modified": "2018-05-11 16:58:31.662866", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Employee Benefit Application", 
diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py
index 9282d98..8e59bf5 100644
--- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py
@@ -4,7 +4,132 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe import _
+from frappe.utils import nowdate, date_diff, getdate
 from frappe.model.document import Document
+from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days
 
 class EmployeeBenefitApplication(Document):
-	pass
+	def validate(self):
+		if self.max_benefits <= 0:
+			frappe.throw(_("Employee {0} has no maximum benefit amount").format(self.employee))
+		self.validate_max_benefit_for_component()
+
+	def before_submit(self):
+		self.validate_duplicate_on_payroll_period()
+
+	def validate_max_benefit_for_component(self):
+		if self.employee_benefits:
+			max_benefit_amount = 0
+			for employee_benefit in self.employee_benefits:
+				self.validate_max_benefit(employee_benefit.earning_component)
+				max_benefit_amount += employee_benefit.amount
+			if max_benefit_amount > self.max_benefits:
+				frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, self.max_benefits))
+
+	def validate_max_benefit(self, earning_component_name):
+		max_benefit_amount = frappe.db.get_value("Salary Component", earning_component_name, "max_benefit_amount")
+		benefit_amount = 0
+		for employee_benefit in self.employee_benefits:
+			if employee_benefit.earning_component == earning_component_name:
+				benefit_amount += employee_benefit.amount
+		if benefit_amount > max_benefit_amount:
+			frappe.throw(_("Maximum benefit amount of component {0} exceeds {1}").format(earning_component_name, max_benefit_amount))
+
+	def validate_duplicate_on_payroll_period(self):
+		application = frappe.db.exists(
+			"Employee Benefit Application",
+			{
+				'employee': self.employee,
+				'payroll_period': self.payroll_period,
+				'docstatus': 1
+			}
+		)
+		if application:
+			frappe.throw(_("Employee {0} already submited an apllication {1} for the payroll period {2}").format(self.employee, application, self.payroll_period))
+
+@frappe.whitelist()
+def get_max_benefits(employee, on_date):
+	sal_struct = get_assigned_salary_sturecture(employee, on_date)
+	if sal_struct:
+		max_benefits = frappe.db.get_value("Salary Structure", sal_struct[0][0], "max_benefits")
+		if max_benefits > 0:
+			return max_benefits
+		else:
+			frappe.throw(_("Employee {0} has no max benefits in salary structure {1}").format(employee, sal_struct[0][0]))
+	else:
+		frappe.throw(_("Employee {0} has no salary structure assigned").format(employee))
+
+
+@frappe.whitelist()
+def get_assigned_salary_sturecture(employee, _date):
+	if not _date:
+		_date = nowdate()
+	salary_structure = frappe.db.sql("""
+		select salary_structure from `tabSalary Structure Assignment`
+		where employee=%(employee)s
+		and docstatus = 1
+		and (
+			(%(_date)s between from_date and ifnull(to_date, '2199-12-31'))
+		)""", {
+			'employee': employee,
+			'_date': _date,
+		})
+	if salary_structure:
+		return salary_structure
+
+def get_employee_benefit_application(salary_slip):
+	employee_benefits = frappe.db.sql("""
+	select name from `tabEmployee Benefit Application`
+	where employee=%(employee)s
+	and docstatus = 1
+	and (date between %(start_date)s and %(end_date)s)
+	""", {
+		'employee': salary_slip.employee,
+		'start_date': salary_slip.start_date,
+		'end_date': salary_slip.end_date
+	})
+
+	if employee_benefits:
+		for employee_benefit in employee_benefits:
+			employee_benefit_obj = frappe.get_doc("Employee Benefit Application", employee_benefit[0])
+			return get_components(employee_benefit_obj, salary_slip)
+
+def get_components(employee_benefit_application, salary_slip):
+	salary_components_array = []
+	group_component_amount = {}
+	payroll_period_days = get_payroll_period_days(salary_slip.start_date, salary_slip.end_date, salary_slip.company)
+	for employee_benefit in employee_benefit_application.employee_benefits:
+		if employee_benefit.is_pro_rata_applicable == 1:
+			struct_row = {}
+			salary_components_dict = {}
+			amount = get_amount(payroll_period_days, salary_slip.start_date, salary_slip.end_date, employee_benefit.amount)
+			sc = frappe.get_doc("Salary Component", employee_benefit.earning_component)
+			salary_component = sc
+			if sc.earning_component_group and not sc.is_group and not sc.flexi_default:
+				salary_component = frappe.get_doc("Salary Component", sc.earning_component_group)
+				if group_component_amount and group_component_amount.has_key(sc.earning_component_group):
+					group_component_amount[sc.earning_component_group] += amount
+				else:
+					group_component_amount[sc.earning_component_group] = amount
+				amount = group_component_amount[sc.earning_component_group]
+			struct_row['depends_on_lwp'] = salary_component.depends_on_lwp
+			struct_row['salary_component'] = salary_component.name
+			struct_row['abbr'] = salary_component.salary_component_abbr
+			struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total
+			salary_components_dict['amount'] = amount
+			salary_components_dict['struct_row'] = struct_row
+			salary_components_array.append(salary_components_dict)
+
+	if len(salary_components_array) > 0:
+		return salary_components_array
+	return False
+
+def get_amount(payroll_period_days, start_date, end_date, amount):
+	salary_slip_days = date_diff(getdate(end_date), getdate(start_date)) + 1
+	amount_per_day = amount / payroll_period_days
+	total_amount = amount_per_day * salary_slip_days
+	if total_amount > amount:
+		return amount
+	else:
+		return total_amount
diff --git a/erpnext/hr/doctype/employee_benefit_application/test_employee_benefit_application.py b/erpnext/hr/doctype/employee_benefit_application/test_employee_benefit_application.py
index 9b915a6..34e1a8f 100644
--- a/erpnext/hr/doctype/employee_benefit_application/test_employee_benefit_application.py
+++ b/erpnext/hr/doctype/employee_benefit_application/test_employee_benefit_application.py
@@ -2,8 +2,6 @@
 # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
 # See license.txt
 from __future__ import unicode_literals
-
-import frappe
 import unittest
 
 class TestEmployeeBenefitApplication(unittest.TestCase):
diff --git a/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json b/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json
index 35918e1..37f3242 100644
--- a/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json
+++ b/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json
@@ -51,6 +51,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "is_pro_rata_applicable", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Is Pro-rata Applicable", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "earning_component.is_pro_rata_applicable", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "amount", 
    "fieldtype": "Currency", 
    "hidden": 0, 
@@ -87,7 +119,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2018-04-13 19:32:35.064272", 
+ "modified": "2018-05-15 12:03:25.545041", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Employee Benefit Application Detail", 
diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js
index 816b1bd..64fde03 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js
+++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js
@@ -2,7 +2,15 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Employee Benefit Claim', {
-	refresh: function(frm) {
-
+	setup: function(frm) {
+		frm.set_query("earning_component", function() {
+			return {
+				filters: {
+					type: "Earning",
+					is_flexible_benefit: true,
+					disabled: false
+				}
+			};
+		});
 	}
 });
diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json
index 00d5159..9da7cdb 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json
+++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json
@@ -188,6 +188,7 @@
    "label": "Max Amount Eligible", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "earning_component.max_benefit_amount", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -207,6 +208,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "is_pro_rata_applicable", 
+   "fieldtype": "Check", 
+   "hidden": 1, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Is Pro-Rata Applicable", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "earning_component.is_pro_rata_applicable", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "claimed_amount", 
    "fieldtype": "Currency", 
    "hidden": 0, 
@@ -367,7 +400,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-04-14 15:38:41.538646", 
+ "modified": "2018-05-16 17:21:25.598531", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Employee Benefit Claim", 
@@ -460,4 +493,4 @@
  "title_field": "employee_name", 
  "track_changes": 1, 
  "track_seen": 0
-} 
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
index 551d1ac..39b3540 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
+++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
@@ -4,7 +4,62 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe import _
 from frappe.model.document import Document
+from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits
 
 class EmployeeBenefitClaim(Document):
-	pass
+	def validate(self):
+		if not self.is_pro_rata_applicable:
+			self.validate_max_benefit_for_sal_struct()
+		# TODO: Validate all cases
+
+	def validate_max_benefit_for_sal_struct(self):
+		max_benefits = get_max_benefits(self.employee, self.claim_date)
+		if self.claimed_amount > max_benefits:
+			frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, max_benefits))
+
+
+def get_employee_benefit_claim(salary_slip):
+	employee_benefits = frappe.db.sql("""
+	select name from `tabEmployee Benefit Claim`
+	where employee=%(employee)s
+	and docstatus = 1 and is_pro_rata_applicable = 0
+	and (claim_date between %(start_date)s and %(end_date)s)
+	""", {
+		'employee': salary_slip.employee,
+		'start_date': salary_slip.start_date,
+		'end_date': salary_slip.end_date
+	})
+
+	if employee_benefits:
+		salary_components_array = []
+		for employee_benefit in employee_benefits:
+			struct_row = {}
+			salary_components_dict = {}
+			group_component_amount = {}
+
+			employee_benefit_claim = frappe.get_doc("Employee Benefit Claim", employee_benefit[0])
+			amount = employee_benefit_claim.claimed_amount
+			sc = frappe.get_doc("Salary Component", employee_benefit_claim.earning_component)
+
+			salary_component = sc
+			if sc.earning_component_group and not sc.is_group and not sc.flexi_default:
+				salary_component = frappe.get_doc("Salary Component", sc.earning_component_group)
+				if group_component_amount and group_component_amount.has_key(sc.earning_component_group):
+					group_component_amount[sc.earning_component_group] += amount
+				else:
+					group_component_amount[sc.earning_component_group] = amount
+				amount = group_component_amount[sc.earning_component_group]
+
+			struct_row['depends_on_lwp'] = salary_component.depends_on_lwp
+			struct_row['salary_component'] = salary_component.name
+			struct_row['abbr'] = salary_component.salary_component_abbr
+			struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total
+			salary_components_dict['amount'] = amount
+			salary_components_dict['struct_row'] = struct_row
+			salary_components_array.append(salary_components_dict)
+
+		if len(salary_components_array) > 0:
+			return salary_components_array
+	return False
diff --git a/erpnext/hr/doctype/employee_benefit_claim/test_employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/test_employee_benefit_claim.py
index e8dc0da..aff73e5 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/test_employee_benefit_claim.py
+++ b/erpnext/hr/doctype/employee_benefit_claim/test_employee_benefit_claim.py
@@ -2,8 +2,6 @@
 # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
 # See license.txt
 from __future__ import unicode_literals
-
-import frappe
 import unittest
 
 class TestEmployeeBenefitClaim(unittest.TestCase):
diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.py b/erpnext/hr/doctype/payroll_period/payroll_period.py
index 1e18388..a818bc4 100644
--- a/erpnext/hr/doctype/payroll_period/payroll_period.py
+++ b/erpnext/hr/doctype/payroll_period/payroll_period.py
@@ -4,7 +4,26 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe.utils import date_diff, getdate
 from frappe.model.document import Document
 
 class PayrollPeriod(Document):
 	pass
+
+def get_payroll_period_days(start_date, end_date, company):
+	payroll_period_dates = frappe.db.sql("""
+	select ppd.start_date, ppd.end_date from `tabPayroll Period Date` ppd, `tabPayroll Period` pp
+	where pp.company=%(company)s
+	and ppd.parent = pp.name
+	and (
+		(%(start_date)s between ppd.start_date and ppd.end_date)
+		or (%(end_date)s between ppd.start_date and ppd.end_date)
+		or (ppd.start_date between %(start_date)s and %(end_date)s)
+	)""", {
+		'company': company,
+		'start_date': start_date,
+		'end_date': end_date
+	})
+
+	if len(payroll_period_dates) > 0:
+		return date_diff(getdate(payroll_period_dates[0][1]), getdate(payroll_period_dates[0][0])) + 1
diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js
index 86203ab..e58a05e 100644
--- a/erpnext/hr/doctype/salary_component/salary_component.js
+++ b/erpnext/hr/doctype/salary_component/salary_component.js
@@ -12,7 +12,15 @@
 					"is_group": 0,
 					"company": d.company
 				}
-			}
-		})
+			};
+		});
+		frm.set_query("earning_component_group", function(frm) {
+			return {
+				filters: {
+					"is_group": 1,
+					"is_flexible_benefit": 1
+				}
+			};
+		});
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json
index cf85af4..6764e0c 100644
--- a/erpnext/hr/doctype/salary_component/salary_component.json
+++ b/erpnext/hr/doctype/salary_component/salary_component.json
@@ -114,70 +114,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "eval:doc.type==\"Earning\"", 
-   "fieldname": "is_tax_applicable", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Is Tax Applicable", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "1", 
-   "fieldname": "is_payable", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Is Payable", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
    "fieldname": "column_break_4", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -366,6 +302,38 @@
    "collapsible": 0, 
    "columns": 0, 
    "depends_on": "is_flexible_benefit", 
+   "fieldname": "is_group", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Is Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "eval:doc.is_flexible_benefit && !doc.is_group && !doc.flexi_default", 
    "fieldname": "earning_component_group", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -460,6 +428,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "depends_on": "eval:doc.is_flexible_benefit && doc.is_pro_rata_applicable", 
+   "fieldname": "flexi_default", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Default Flexible Component", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "depends_on": "is_flexible_benefit", 
    "fieldname": "only_tax_impact", 
    "fieldtype": "Check", 
@@ -618,7 +618,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "is_payable", 
    "fieldname": "section_break_5", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -1002,7 +1001,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-05-16 12:15:43.117948", 
+ "modified": "2018-05-16 12:27:03.005070", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Salary Component", 
@@ -1037,4 +1036,4 @@
  "sort_order": "DESC", 
  "track_changes": 0, 
  "track_seen": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py
index beffaec..132930f 100644
--- a/erpnext/hr/doctype/salary_component/salary_component.py
+++ b/erpnext/hr/doctype/salary_component/salary_component.py
@@ -4,12 +4,27 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe import _
 from frappe.model.document import Document
 from frappe.model.naming import append_number_if_name_exists
 
 class SalaryComponent(Document):
 	def validate(self):
 		self.validate_abbr()
+		self.validate_flexi_default()
+
+	def validate_flexi_default(self):
+		if self.is_flexible_benefit and self.is_pro_rata_applicable and self.flexi_default:
+			salary_component = frappe.db.exists(
+				'Salary Component',
+				{
+					'is_flexible_benefit': 1,
+					'is_pro_rata_applicable': 1,
+					'flexi_default': 1
+				}
+			)
+			if salary_component and salary_component != self.name:
+				frappe.throw(_("{0} is already marked as default flexible component").format(salary_component))
 
 	def validate_abbr(self):
 		if not self.salary_component_abbr:
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 53e6aa4..87511b6 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -13,6 +13,9 @@
 from erpnext.utilities.transaction_base import TransactionBase
 from frappe.utils.background_jobs import enqueue
 from erpnext.hr.doctype.additional_salary_component.additional_salary_component import get_additional_salary_component
+from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_employee_benefit_application, get_amount
+from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days
+from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_employee_benefit_claim
 from erpnext.hr.utils import get_payroll_period
 
 class SalarySlip(TransactionBase):
@@ -68,7 +71,57 @@
 		if additional_components:
 			for additional_component in additional_components:
 				additional_component = frappe._dict(additional_component)
-				self.update_component_row(frappe._dict(additional_component.struct_row), additional_component.amount, "earnings")
+				amount = self.update_amount_for_other_component(frappe._dict(additional_component.struct_row).salary_component, additional_component.amount)
+				self.update_component_row(frappe._dict(additional_component.struct_row), amount, "earnings")
+
+		max_benefits = self._salary_structure_doc.get("max_benefits")
+		if max_benefits > 0:
+			employee_benefits = get_employee_benefit_application(self)
+			if employee_benefits:
+				for employee_benefit in employee_benefits:
+					benefit_component = frappe._dict(employee_benefit)
+					amount = self.update_amount_for_other_component(frappe._dict(benefit_component.struct_row).salary_component, benefit_component.amount)
+					self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings")
+			else:
+				default_flexi_compenent = frappe.db.exists(
+					'Salary Component',
+					{
+						'is_flexible_benefit': 1,
+						'is_pro_rata_applicable': 1,
+						'flexi_default': 1
+					}
+				)
+				if default_flexi_compenent:
+					flexi_struct_row = self.create_flexi_struct_row(default_flexi_compenent)
+					payroll_period_days = get_payroll_period_days(self.start_date, self.end_date, self.company)
+					amount = self.update_amount_for_other_component(default_flexi_compenent, get_amount(payroll_period_days, self.start_date, self.end_date, max_benefits))
+					self.update_component_row(flexi_struct_row, amount, "earnings")
+				else:
+					frappe.throw(_("Configure default flexible benefit salary component for apply pro-rata benefit"))
+
+			benefit_claims = get_employee_benefit_claim(self)
+			if benefit_claims:
+				for benefit_claim in benefit_claims:
+					benefit_component = frappe._dict(benefit_claim)
+					amount = self.update_amount_for_other_component(frappe._dict(benefit_component.struct_row).salary_component, benefit_component.amount)
+					self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings")
+
+	def update_amount_for_other_component(self, salary_component, new_amount):
+		amount = new_amount
+		for d in self.get("earnings"):
+			if d.salary_component == salary_component:
+				d.amount += new_amount
+				amount = d.amount
+		return amount
+
+	def create_flexi_struct_row(self, default_flexi_compenent):
+		salary_component = frappe.get_doc("Salary Component", default_flexi_compenent)
+		flexi_struct_row = {}
+		flexi_struct_row['depends_on_lwp'] = salary_component.depends_on_lwp
+		flexi_struct_row['salary_component'] = salary_component.name
+		flexi_struct_row['abbr'] = salary_component.salary_component_abbr
+		flexi_struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total
+		return frappe._dict(flexi_struct_row)
 
 	def update_component_row(self, struct_row, amount, key):
 		component_row = None
@@ -181,6 +234,7 @@
 		st_name = frappe.db.sql("""select salary_structure from `tabSalary Structure Assignment`
 			where employee=%s and (from_date <= %s or from_date <= %s)
 			and (to_date is null or to_date >= %s or to_date >= %s)
+			and docstatus = 1
 			and salary_structure in (select name from `tabSalary Structure`
 				where is_active = 'Yes'%s)
 			"""% ('%s', '%s', '%s','%s','%s', cond),(self.employee, self.start_date, joining_date, self.end_date, relieving_date))
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index 8fd51d9..9e62b66 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -123,15 +123,6 @@
 	}
 });
 
-frappe.ui.form.on('Salary Structure Employee', {
-	from_date: function(frm, cdt, cdn) {
-		validate_date(frm, cdt, cdn);
-	},
-	to_date: function(frm, cdt, cdn) {
-		validate_date(frm, cdt, cdn);
-	}
-});
-
 var validate_date = function(frm, cdt, cdn) {
 	var doc = locals[cdt][cdn];
 	if(doc.to_date && doc.from_date) {