Employee Benefit (#14571)

* Rename - filed is_pro_rata_applicable to pay_against_benefit_claim

* Employee Benefit Application - Validate previous benefit claim

* Employee Benefit Claim - Code refactor

* Salary Slip - additional salary - fix
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 2a8ce91..9af3ee9 100644
--- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js
+++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js
@@ -78,7 +78,7 @@
 		if(cint(tbl[i].amount) > 0) {
 			total_amount += flt(tbl[i].amount);
 		}
-		if(tbl[i].is_pro_rata_applicable == 1){
+		if(tbl[i].pay_against_benefit_claim != 1){
 			pro_rata_dispensed_amount += flt(tbl[i].amount);
 		}
 	}
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 e093769..45e2d65 100644
--- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py
@@ -9,7 +9,7 @@
 from frappe.model.document import Document
 from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days
 from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure
-from erpnext.hr.utils import get_sal_slip_total_benefit_given, get_holidays_for_employee
+from erpnext.hr.utils import get_sal_slip_total_benefit_given, get_holidays_for_employee, get_previous_claimed_amount
 
 class EmployeeBenefitApplication(Document):
 	def validate(self):
@@ -17,9 +17,22 @@
 		if self.max_benefits <= 0:
 			frappe.throw(_("Employee {0} has no maximum benefit amount").format(self.employee))
 		self.validate_max_benefit_for_component()
+		self.validate_prev_benefit_claim()
 		if self.remainig_benefits > 0:
 			self.validate_remaining_benefit_amount()
 
+	def validate_prev_benefit_claim(self):
+		if self.employee_benefits:
+			for benefit in self.employee_benefits:
+				if benefit.pay_against_benefit_claim == 1:
+					payroll_period = frappe.get_doc("Payroll Period", self.payroll_period)
+					benefit_claimed = get_previous_claimed_amount(self.employee, payroll_period, component = benefit.earning_component)
+					benefit_given = get_sal_slip_total_benefit_given(self.employee, payroll_period, component = benefit.earning_component)
+					benefit_claim_remining = benefit_claimed - benefit_given
+					if benefit_claimed > 0 and benefit_claim_remining > benefit.amount:
+						frappe.throw(_("An amount of {0} already claimed for the component {1},\
+						 set the amount equal or greater than {2}").format(benefit_claimed, benefit.earning_component, benefit_claim_remining))
+
 	def validate_remaining_benefit_amount(self):
 		# check salary structure earnings have flexi component (sum of max_benefit_amount)
 		# without pro-rata which satisfy the remainig_benefits
@@ -37,8 +50,8 @@
 			if salary_structure.earnings:
 				for earnings in salary_structure.earnings:
 					if earnings.is_flexible_benefit == 1 and earnings.salary_component not in benefit_components:
-						is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", earnings.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"])
-						if is_pro_rata_applicable == 1:
+						pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", earnings.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
+						if pay_against_benefit_claim != 1:
 							pro_rata_amount += max_benefit_amount
 						else:
 							non_pro_rata_amount += max_benefit_amount
@@ -113,7 +126,7 @@
 				sal_struct = frappe.get_doc("Salary Structure", sal_struct_name)
 				for sal_struct_row in sal_struct.get("earnings"):
 					salary_component = frappe.get_doc("Salary Component", sal_struct_row.salary_component)
-					if salary_component.depends_on_lwp == 1 and salary_component.is_pro_rata_applicable == 1:
+					if salary_component.depends_on_lwp == 1 and salary_component.pay_against_benefit_claim != 1:
 						have_depends_on_lwp = True
 						benefit_amount = get_benefit_pro_rata_ratio_amount(sal_struct, salary_component.max_benefit_amount)
 						amount_per_day = benefit_amount / payroll_period_days
@@ -188,8 +201,8 @@
 	total_pro_rata_max = 0
 	benefit_amount = 0
 	for sal_struct_row in sal_struct.get("earnings"):
-		is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"])
-		if sal_struct_row.is_flexible_benefit == 1 and is_pro_rata_applicable == 1:
+		pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
+		if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
 			total_pro_rata_max += max_benefit_amount
 	if total_pro_rata_max > 0:
 		benefit_amount = component_max * sal_struct.max_benefits / total_pro_rata_max
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 eba9b19..480ec5b 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
@@ -53,8 +53,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fetch_from": "earning_component.is_pro_rata_applicable", 
-   "fieldname": "is_pro_rata_applicable", 
+   "fetch_from": "earning_component.pay_against_benefit_claim", 
+   "fieldname": "pay_against_benefit_claim", 
    "fieldtype": "Check", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
@@ -63,7 +63,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Is Pro-rata Applicable", 
+   "label": "Pay Against Benefit Claim", 
    "length": 0, 
    "no_copy": 0, 
    "options": "", 
@@ -157,7 +157,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2018-05-26 12:00:37.588822", 
+ "modified": "2018-06-13 17:34:57.783584", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Employee Benefit Application Detail", 
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 a59aaea..59b6a6c 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json
+++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json
@@ -43,7 +43,7 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -77,7 +77,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -87,38 +87,39 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fetch_from": "employee.department",
-   "fieldname": "department",
-   "fieldtype": "Link",
-   "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": "Department",
-   "length": 0,
-   "no_copy": 0,
-   "options": "Department",
-   "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,
+   "fetch_from": "employee.department", 
+   "fieldname": "department", 
+   "fieldtype": "Link", 
+   "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": "Department", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Department", 
+   "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,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "columns": 0, 
    "default": "Today", 
    "fieldname": "claim_date", 
@@ -143,7 +144,7 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -174,7 +175,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -207,7 +208,7 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -241,7 +242,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -251,8 +252,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fetch_from": "earning_component.is_pro_rata_applicable", 
-   "fieldname": "is_pro_rata_applicable", 
+   "fetch_from": "earning_component.pay_against_benefit_claim", 
+   "fieldname": "pay_against_benefit_claim", 
    "fieldtype": "Check", 
    "hidden": 1, 
    "ignore_user_permissions": 0, 
@@ -261,7 +262,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Is Pro-Rata Applicable", 
+   "label": "Pay Against Benefit Claim", 
    "length": 0, 
    "no_copy": 0, 
    "options": "", 
@@ -269,7 +270,7 @@
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 0, 
+   "read_only": 1, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -307,7 +308,7 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -340,7 +341,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -372,7 +373,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -403,7 +404,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
@@ -435,7 +436,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }
  ], 
@@ -449,7 +450,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-05-26 12:43:21.082282",
+ "modified": "2018-06-18 11:14:59.895298", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Employee Benefit Claim", 
@@ -542,4 +543,4 @@
  "title_field": "employee_name", 
  "track_changes": 1, 
  "track_seen": 0
-}
+}
\ 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 69e19bc..6f57bd6 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
+++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
@@ -7,7 +7,7 @@
 from frappe import _
 from frappe.model.document import Document
 from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits
-from erpnext.hr.utils import get_payroll_period
+from erpnext.hr.utils import get_payroll_period, get_previous_claimed_amount
 from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure
 
 class EmployeeBenefitClaim(Document):
@@ -21,12 +21,12 @@
 		self.validate_max_benefit_for_component(payroll_period)
 		self.validate_max_benefit_for_sal_struct(max_benefits)
 		self.validate_benefit_claim_amount(max_benefits, payroll_period)
-		if not self.is_pro_rata_applicable:
+		if self.pay_against_benefit_claim:
 			self.validate_non_pro_rata_benefit_claim(max_benefits, payroll_period)
 
 	def validate_benefit_claim_amount(self, max_benefits, payroll_period):
 		claimed_amount = self.claimed_amount
-		claimed_amount += self.get_previous_claimed_amount(payroll_period)
+		claimed_amount += get_previous_claimed_amount(self.employee, payroll_period)
 		if max_benefits < claimed_amount:
 			frappe.throw(_("Maximum benefit of employee {0} exceeds {1} by the sum {2} of previous claimed\
 			amount").format(self.employee, max_benefits, claimed_amount-max_benefits))
@@ -37,7 +37,7 @@
 
 	def validate_max_benefit_for_component(self, payroll_period):
 		claimed_amount = self.claimed_amount
-		claimed_amount += self.get_previous_claimed_amount(payroll_period, self.earning_component)
+		claimed_amount += get_previous_claimed_amount(self.employee, payroll_period, component = self.earning_component)
 		if claimed_amount > self.max_amount_eligible:
 			frappe.throw(_("Maximum amount eligible for the component {0} exceeds {1}").format(self.earning_component, self.max_amount_eligible))
 
@@ -51,7 +51,7 @@
 		if not pro_rata_amount:
 			pro_rata_amount = 0
 
-		claimed_amount += self.get_previous_claimed_amount(payroll_period, True)
+		claimed_amount += get_previous_claimed_amount(self.employee, payroll_period, non_pro_rata = True)
 		if max_benefits < pro_rata_amount + claimed_amount:
 			frappe.throw(_("Maximum benefit of employee {0} exceeds {1} by the sum {2} of benefit application pro-rata component\
 			amount and previous claimed amount").format(self.employee, max_benefits, pro_rata_amount+claimed_amount-max_benefits))
@@ -63,13 +63,13 @@
 			total_pro_rata_max = 0
 			benefit_amount_total = 0
 			for sal_struct_row in sal_struct.get("earnings"):
-				is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"])
-				if sal_struct_row.is_flexible_benefit == 1 and is_pro_rata_applicable == 1:
+				pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
+				if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
 					total_pro_rata_max += max_benefit_amount
 			if total_pro_rata_max > 0:
 				for sal_struct_row in sal_struct.get("earnings"):
-					is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"])
-					if sal_struct_row.is_flexible_benefit == 1 and is_pro_rata_applicable == 1:
+					pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
+					if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
 						component_max = max_benefit_amount
 						benefit_amount = component_max * sal_struct.max_benefits / total_pro_rata_max
 						if benefit_amount > component_max:
@@ -91,35 +91,11 @@
 			return frappe.db.get_value("Employee Benefit Application", application, "pro_rata_dispensed_amount")
 		return False
 
-	def get_previous_claimed_amount(self, payroll_period, non_pro_rata=False, component=False):
-		total_claimed_amount = 0
-		query = """
-		select sum(claimed_amount) as 'total_amount'
-		from `tabEmployee Benefit Claim`
-		where employee=%(employee)s
-		and docstatus = 1
-		and (claim_date between %(start_date)s and %(end_date)s)
-		"""
-		if non_pro_rata:
-			query += "and is_pro_rata_applicable = 0"
-		if component:
-			query += "and earning_component = %(component)s"
-
-		sum_of_claimed_amount = frappe.db.sql(query, {
-			'employee': self.employee,
-			'start_date': payroll_period.start_date,
-			'end_date': payroll_period.end_date,
-			'component': component
-		}, as_dict=True)
-		if sum_of_claimed_amount and sum_of_claimed_amount[0].total_amount > 0:
-			total_claimed_amount = sum_of_claimed_amount[0].total_amount
-		return total_claimed_amount
-
 def get_benefit_claim_amount(employee, start_date, end_date, struct_row):
 	benefit_claim_details = frappe.db.sql("""
 	select claimed_amount from `tabEmployee Benefit Claim`
 	where employee=%(employee)s
-	and docstatus = 1 and is_pro_rata_applicable = 0
+	and docstatus = 1 and pay_against_benefit_claim = 1
 	and earning_component = %(earning_component)s
 	and (claim_date between %(start_date)s and %(end_date)s)
 	""", {
diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json
index fd6fb17..e3543bf 100644
--- a/erpnext/hr/doctype/salary_component/salary_component.json
+++ b/erpnext/hr/doctype/salary_component/salary_component.json
@@ -540,7 +540,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "depends_on": "is_flexible_benefit", 
-   "fieldname": "is_pro_rata_applicable", 
+   "fieldname": "pay_against_benefit_claim", 
    "fieldtype": "Check", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
@@ -549,7 +549,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Is Pro-rata Applicable", 
+   "label": "Pay Against Benefit Claim", 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -1002,7 +1002,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-06-19 11:37:27.521796", 
+ "modified": "2018-06-19 11:37:37.521796", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Salary Component", 
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 47f1cc4..94f80e1 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -87,7 +87,7 @@
 					self.update_component_row(frappe._dict(tax_row), amount, "deductions")
 
 	def add_employee_flexi_benefits(self, struct_row):
-		if frappe.db.get_value("Salary Component", struct_row.salary_component, "is_pro_rata_applicable") == 1:
+		if frappe.db.get_value("Salary Component", struct_row.salary_component, "pay_against_benefit_claim") != 1:
 			benefit_component_amount = get_benefit_component_amount(self.employee, self.start_date, self.end_date, struct_row, self._salary_structure_doc, self.payment_days, self.total_working_days)
 			if benefit_component_amount:
 				self.update_component_row(struct_row, benefit_component_amount, "earnings")
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index d8636ed..42cf0a9 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -353,3 +353,27 @@
 	# Don't delete this method, used for localization
 	# Indian HRA Exemption Calculation
 	return {}
+
+def get_previous_claimed_amount(employee, payroll_period, non_pro_rata=False, component=False):
+	total_claimed_amount = 0
+	query = """
+	select sum(claimed_amount) as 'total_amount'
+	from `tabEmployee Benefit Claim`
+	where employee=%(employee)s
+	and docstatus = 1
+	and (claim_date between %(start_date)s and %(end_date)s)
+	"""
+	if non_pro_rata:
+		query += "and pay_against_benefit_claim = 1"
+	if component:
+		query += "and earning_component = %(component)s"
+
+	sum_of_claimed_amount = frappe.db.sql(query, {
+		'employee': employee,
+		'start_date': payroll_period.start_date,
+		'end_date': payroll_period.end_date,
+		'component': component
+	}, as_dict=True)
+	if sum_of_claimed_amount and sum_of_claimed_amount[0].total_amount > 0:
+		total_claimed_amount = sum_of_claimed_amount[0].total_amount
+	return total_claimed_amount