def get_max_benefits(employee, on_date):
	sal_struct = get_assigned_salary_structure(employee, on_date)
	if sal_struct:
		max_benefits = frappe.db.get_value("Salary Structure", sal_struct, "max_benefits")
		if max_benefits > 0:
			return max_benefits
	return False
    def validate_non_pro_rata_benefit_claim(self, max_benefits,
                                            payroll_period):
        claimed_amount = self.claimed_amount
        pro_rata_amount = self.get_pro_rata_amount_in_application(
            payroll_period.name)
        if not pro_rata_amount:
            pro_rata_amount = 0
            # Get pro_rata_amount if there is no application,
            # get salary structure for the date and calculate pro-rata amount
            sal_struct_name = get_assigned_salary_structure(
                self.employee, self.claim_date)
            if sal_struct_name:
                sal_struct = frappe.get_doc("Salary Structure",
                                            sal_struct_name)
                pro_rata_amount = get_benefit_pro_rata_ratio_amount(
                    self.employee, self.claim_date, sal_struct)

        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))
	def validate_remaining_benefit_amount(self):
		# check salary structure earnings have flexi component (sum of max_benefit_amount)
		# without pro-rata which satisfy the remaining_benefit
		# else pro-rata component for the amount
		# again comes the same validation and satisfy or throw
		benefit_components = []
		if self.employee_benefits:
			for employee_benefit in self.employee_benefits:
				benefit_components.append(employee_benefit.earning_component)
		salary_struct_name = get_assigned_salary_structure(self.employee, self.date)
		if salary_struct_name:
			non_pro_rata_amount = 0
			pro_rata_amount = 0
			salary_structure = frappe.get_doc("Salary Structure", salary_struct_name)
			if salary_structure.earnings:
				for earnings in salary_structure.earnings:
					if earnings.is_flexible_benefit == 1 and earnings.salary_component not in benefit_components:
						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

			if pro_rata_amount == 0  and non_pro_rata_amount == 0:
				frappe.throw(_("Please add the remaining benefits {0} to any of the existing component").format(self.remaining_benefit))
			elif non_pro_rata_amount > 0 and non_pro_rata_amount < rounded(self.remaining_benefit):
				frappe.throw(_("You can claim only an amount of {0}, the rest amount {1} should be in the application \
				as pro-rata component").format(non_pro_rata_amount, self.remaining_benefit - non_pro_rata_amount))
			elif non_pro_rata_amount == 0:
				frappe.throw(_("Please add the remaining benefits {0} to the application as \
				pro-rata component").format(self.remaining_benefit))
def get_max_benefits(employee, on_date):
	sal_struct = get_assigned_salary_structure(employee, on_date)
	if sal_struct:
		max_benefits = frappe.db.get_value("Salary Structure", sal_struct, "max_benefits")
		if max_benefits > 0:
			return max_benefits
	return False
	def validate_remaining_benefit_amount(self):
		# check salary structure earnings have flexi component (sum of max_benefit_amount)
		# without pro-rata which satisfy the remaining_benefit
		# else pro-rata component for the amount
		# again comes the same validation and satisfy or throw
		benefit_components = []
		if self.employee_benefits:
			for employee_benefit in self.employee_benefits:
				benefit_components.append(employee_benefit.earning_component)
		salary_struct_name = get_assigned_salary_structure(self.employee, self.date)
		if salary_struct_name:
			non_pro_rata_amount = 0
			pro_rata_amount = 0
			salary_structure = frappe.get_doc("Salary Structure", salary_struct_name)
			if salary_structure.earnings:
				for earnings in salary_structure.earnings:
					if earnings.is_flexible_benefit == 1 and earnings.salary_component not in benefit_components:
						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

			if pro_rata_amount == 0  and non_pro_rata_amount == 0:
				frappe.throw(_("Please add the remaining benefits {0} to any of the existing component").format(self.remaining_benefit))
			elif non_pro_rata_amount > 0 and non_pro_rata_amount < rounded(self.remaining_benefit):
				frappe.throw(_("You can claim only an amount of {0}, the rest amount {1} should be in the application \
				as pro-rata component").format(non_pro_rata_amount, self.remaining_benefit - non_pro_rata_amount))
			elif non_pro_rata_amount == 0:
				frappe.throw(_("Please add the remaining benefits {0} to the application as \
				pro-rata component").format(self.remaining_benefit))
Example #6
0
    def get_leave_details_for_encashment(self):
        salary_structure = get_assigned_salary_structure(
            self.employee, self.encashment_date or getdate(nowdate()))
        if not salary_structure:
            frappe.throw(
                _("No Salary Structure assigned for Employee {0} on given date {1}"
                  ).format(self.employee, self.encashment_date))

        if not frappe.db.get_value("Leave Type", self.leave_type,
                                   'allow_encashment'):
            frappe.throw(
                _("Leave Type {0} is not encashable").format(self.leave_type))

        allocation = self.get_leave_allocation()

        if not allocation:
            frappe.throw(
                _("No Leaves Allocated to Employee: {0} for Leave Type: {1}").
                format(self.employee, self.leave_type))

        self.leave_balance = allocation.total_leaves_allocated - allocation.carry_forwarded_leaves_count\
         - get_unused_leaves(self.employee, self.leave_type, allocation.from_date, self.encashment_date)

        encashable_days = self.leave_balance - frappe.db.get_value(
            'Leave Type', self.leave_type, 'encashment_threshold_days')
        self.encashable_days = encashable_days if encashable_days > 0 else 0

        per_day_encashment = frappe.db.get_value(
            'Salary Structure', salary_structure,
            'leave_encashment_amount_per_day')
        self.encashment_amount = self.encashable_days * per_day_encashment if per_day_encashment > 0 else 0

        self.leave_allocation = allocation.name
        return True
Example #7
0
    def get_leave_details_for_encashment(self):
        salary_structure = get_assigned_salary_structure(
            self.employee, self.encashment_date or getdate(nowdate()))
        if not salary_structure:
            frappe.throw(
                _("No Salary Structure assigned for Employee {0} on given date {1}"
                  ).format(self.employee, self.encashment_date))

        if not frappe.db.get_value("Leave Type", self.leave_type,
                                   'allow_encashment'):
            frappe.throw(
                _("Leave Type {0} is not encashable").format(self.leave_type))

        self.leave_balance = get_leave_balance_on(
            self.employee,
            self.leave_type,
            self.encashment_date or getdate(nowdate()),
            consider_all_leaves_in_the_allocation_period=True)

        encashable_days = self.leave_balance - frappe.db.get_value(
            'Leave Type', self.leave_type, 'encashment_threshold_days')
        self.encashable_days = encashable_days if encashable_days > 0 else 0

        per_day_encashment = frappe.db.get_value(
            'Salary Structure', salary_structure,
            'leave_encashment_amount_per_day')
        self.encashment_amount = self.encashable_days * per_day_encashment if per_day_encashment > 0 else 0

        self.leave_allocation = self.get_leave_allocation()
        return True
Example #8
0
 def get_employee_charge_per_hour(self, employee):
     salary_structure = get_assigned_salary_structure(
         employee.name, today())
     if not salary_structure:
         return 0.0
     salary_structure = frappe.get_doc("Salary Structure", salary_structure)
     if salary_structure.docstatus != 1 or not salary_structure.is_active == "Yes" or \
             not salary_structure.salary_slip_based_on_timesheet:
         return 0.0
     return salary_structure.hour_rate
Example #9
0
def create_leave_encashment(leave_allocation):
    ''' Creates leave encashment for the given allocations '''
    for allocation in leave_allocation:
        if not get_assigned_salary_structure(allocation.employee,
                                             allocation.to_date):
            continue
        leave_encashment = frappe.get_doc(
            dict(doctype="Leave Encashment",
                 leave_period=allocation.leave_period,
                 employee=allocation.employee,
                 leave_type=allocation.leave_type,
                 encashment_date=allocation.to_date))
        leave_encashment.insert(ignore_permissions=True)
def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
	if len(filters) < 2:
		return {}

	salary_structure = get_assigned_salary_structure(filters['employee'], filters['date'])

	if salary_structure:
		return frappe.db.sql("""
			select salary_component
			from `tabSalary Detail`
			where parent = %s and is_flexible_benefit = 1
			order by name
		""", salary_structure)
	else:
		frappe.throw(_("Salary Structure not found for employee {0} and date {1}")
			.format(filters['employee'], filters['date']))
	def validate_non_pro_rata_benefit_claim(self, max_benefits, payroll_period):
		claimed_amount = self.claimed_amount
		pro_rata_amount = self.get_pro_rata_amount_in_application(payroll_period.name)
		if not pro_rata_amount:
			pro_rata_amount = 0
			# Get pro_rata_amount if there is no application,
			# get salary structure for the date and calculate pro-rata amount
			sal_struct_name = get_assigned_salary_structure(self.employee, self.claim_date)
			if sal_struct_name:
				sal_struct = frappe.get_doc("Salary Structure", sal_struct_name)
				pro_rata_amount = get_benefit_pro_rata_ratio_amount(self.employee, self.claim_date, sal_struct)

		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))
Example #12
0
    def get_worked_hours(self):
        attendance = frappe.db.sql(
            "select actual_working_hours_work from `tabAttendance` where employee='{0}' and attendance_date between '{1}' and '{2}' and docstatus=1 "
            .format(self.employee, self.start_date, self.end_date))

        absent_hours = 0
        absent_days = frappe.db.sql(
            "select count(name) from `tabAttendance` where employee='{0}' and status='Absent' and attendance_date between '{1}' and '{2}' and docstatus=1 "
            .format(self.employee, self.start_date, self.end_date))[0][0]
        if absent_days >= 5:
            absent_days = absent_days + calendar.FRIDAY
        absent_hours = absent_days * 8

        salary_structure = get_assigned_salary_structure(
            self.employee, self.end_date or getdate(nowdate()))
        if salary_structure:
            salary = frappe.db.sql(
                "select amount from `tabSalary Detail` where parenttype='Salary Structure' and salary_component='Basic' and parent='{0}'"
                .format(salary_structure))
            if salary:
                emp_salary = salary[0][0]
        else:
            emp_salary = 0

        hours = 0
        minutes = 0
        hour_rate = 0
        i = 1
        if attendance[0][0]:
            for day_working_hours in attendance:
                hours += flt(day_working_hours[0].split(":")[0])
                minutes += flt(day_working_hours[0].split(":")[1])

                while i == 1:
                    if minutes >= 60:
                        hours = hours + 1
                        minutes = minutes - 60
                    else:
                        if minutes >= 30:
                            hours = hours + 1
                        i = 0

        self.current_month_worked_hours = hours - absent_hours
        self.hour_rate_work = emp_salary / 30
        self.hours_diff = self.monthly_total_hours - self.current_month_worked_hours
        self.total_deduction_hours = self.hours_diff * self.hour_rate_work * -1
def get_earning_components(doctype, txt, searchfield, start, page_len,
                           filters):
    if len(filters) < 2:
        return {}
    employee = filters['employee']
    date = filters['date']
    salary_structure = get_assigned_salary_structure(employee, date)

    if salary_structure:
        query = """select salary_component from `tabSalary Detail` where parent = '{salary_structure}'
		and is_flexible_benefit = 1
		order by name"""

        return frappe.db.sql(
            query.format(**{"salary_structure": salary_structure}))

    return {}
def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
	if len(filters) < 2:
		return {}
	employee = filters['employee']
	date = filters['date']
	salary_structure = get_assigned_salary_structure(employee, date)

	if salary_structure:
		query = """select salary_component from `tabSalary Detail` where parent = '{salary_structure}'
		and is_flexible_benefit = 1
		order by name"""

		return frappe.db.sql(query.format(**{
			"salary_structure": salary_structure
		}))

	return {}
def get_max_benefits_remaining(employee, on_date, payroll_period):
    max_benefits = get_max_benefits(employee, on_date)
    if max_benefits and max_benefits > 0:
        have_depends_on_payment_days = False
        per_day_amount_total = 0
        payroll_period_days = get_payroll_period_days(on_date, on_date,
                                                      employee)[0]
        payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)

        # Get all salary slip flexi amount in the payroll period
        prev_sal_slip_flexi_total = get_sal_slip_total_benefit_given(
            employee, payroll_period_obj)

        if prev_sal_slip_flexi_total > 0:
            # Check salary structure hold depends_on_payment_days component
            # If yes then find the amount per day of each component and find the sum
            sal_struct_name = get_assigned_salary_structure(employee, on_date)
            if sal_struct_name:
                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_payment_days == 1 and salary_component.pay_against_benefit_claim != 1:
                        have_depends_on_payment_days = True
                        benefit_amount = get_benefit_pro_rata_ratio_amount(
                            sal_struct, salary_component.max_benefit_amount)
                        amount_per_day = benefit_amount / payroll_period_days
                        per_day_amount_total += amount_per_day

            # Then the sum multiply with the no of lwp in that period
            # Include that amount to the prev_sal_slip_flexi_total to get the actual
            if have_depends_on_payment_days and per_day_amount_total > 0:
                holidays = get_holidays_for_employee(
                    employee, payroll_period_obj.start_date, on_date)
                working_days = date_diff(on_date,
                                         payroll_period_obj.start_date) + 1
                leave_days = calculate_lwp(employee,
                                           payroll_period_obj.start_date,
                                           holidays, working_days)
                leave_days_amount = leave_days * per_day_amount_total
                prev_sal_slip_flexi_total += leave_days_amount

            return max_benefits - prev_sal_slip_flexi_total
    return max_benefits
Example #16
0
    def update_hourly_costs(self):
        """
        Called from update_costs button.
        Get the hour rate from assigned salary structure
        Set to hourly cost
        Update costs
        :return:
        """
        for detail in self.details:
            hourly_cost = 0.00

            salary_structure = get_assigned_salary_structure(
                detail.employee, today())
            if salary_structure:
                hour_rate = frappe.db.get_value('Salary Structure',
                                                salary_structure, 'hour_rate')
                hourly_cost = hour_rate

            detail.hourly_cost = hourly_cost
	def get_leave_details_for_encashment(self):
		salary_structure = get_assigned_salary_structure(self.employee, self.encashment_date or getdate(nowdate()))
		if not salary_structure:
			frappe.throw(_("No Salary Structure assigned for Employee {0} on given date {1}").format(self.employee, self.encashment_date))

		if not frappe.db.get_value("Leave Type", self.leave_type, 'allow_encashment'):
			frappe.throw(_("Leave Type {0} is not encashable").format(self.leave_type))

		self.leave_balance = get_leave_balance_on(self.employee, self.leave_type,
			self.encashment_date or getdate(nowdate()), consider_all_leaves_in_the_allocation_period=True)

		encashable_days = self.leave_balance - frappe.db.get_value('Leave Type', self.leave_type, 'encashment_threshold_days')
		self.encashable_days = encashable_days if encashable_days > 0 else 0

		per_day_encashment = frappe.db.get_value('Salary Structure', salary_structure , 'leave_encashment_amount_per_day')
		self.encashment_amount = self.encashable_days * per_day_encashment if per_day_encashment > 0 else 0

		self.leave_allocation = self.get_leave_allocation()
		return True
def get_max_benefits_remaining(employee, on_date, payroll_period):
	max_benefits = get_max_benefits(employee, on_date)
	if max_benefits and max_benefits > 0:
		have_depends_on_payment_days = False
		per_day_amount_total = 0
		payroll_period_days = get_payroll_period_days(on_date, on_date, employee)[0]
		payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)

		# Get all salary slip flexi amount in the payroll period
		prev_sal_slip_flexi_total = get_sal_slip_total_benefit_given(employee, payroll_period_obj)

		if prev_sal_slip_flexi_total > 0:
			# Check salary structure hold depends_on_payment_days component
			# If yes then find the amount per day of each component and find the sum
			sal_struct_name = get_assigned_salary_structure(employee, on_date)
			if sal_struct_name:
				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_payment_days == 1 and salary_component.pay_against_benefit_claim != 1:
						have_depends_on_payment_days = True
						benefit_amount = get_benefit_pro_rata_ratio_amount(sal_struct, salary_component.max_benefit_amount)
						amount_per_day = benefit_amount / payroll_period_days
						per_day_amount_total += amount_per_day

			# Then the sum multiply with the no of lwp in that period
			# Include that amount to the prev_sal_slip_flexi_total to get the actual
			if have_depends_on_payment_days and per_day_amount_total > 0:
				holidays = get_holidays_for_employee(employee, payroll_period_obj.start_date, on_date)
				working_days = date_diff(on_date, payroll_period_obj.start_date) + 1
				leave_days = calculate_lwp(employee, payroll_period_obj.start_date, holidays, working_days)
				leave_days_amount = leave_days * per_day_amount_total
				prev_sal_slip_flexi_total += leave_days_amount

			return max_benefits - prev_sal_slip_flexi_total
	return max_benefits
    def get_leave_details_for_encashment(self,
                                         current_days=0.0,
                                         encashment_amount=0.0):
        self.encasha_amount_from_out = encashment_amount
        self.salary_structure = get_assigned_salary_structure(
            self.employee, self.encashment_date or getdate(nowdate()))
        if not self.salary_structure:
            frappe.throw(
                _("No Salary Structure assigned for Employee {0} on given date {1}"
                  ).format(self.employee, self.encashment_date))

        if not frappe.db.get_value("Leave Type", self.leave_type,
                                   'allow_encashment'):
            frappe.throw(
                _("Leave Type {0} is not encashable").format(self.leave_type))

        self.leave_balance = get_leave_balance_on(
            self.employee,
            self.leave_type,
            self.encashment_date or getdate(nowdate()),
            consider_all_leaves_in_the_allocation_period=True)

        if flt(current_days) > 0:
            encashable_days = current_days
            self.encashable_days_from_out = current_days
        else:
            encashable_days = ((self.leave_balance - frappe.db.get_value(
                'Leave Type', self.leave_type, 'encashment_threshold_days'))
                               if self.encashable_days_from_out == 0.0 else
                               self.encashable_days_from_out)
        # frappe.msgprint(str(self.encashment_amount))
        if encashment_amount == None:  #or encashment_amount != self.encashment_amount:

            self.encashable_days = flt(
                encashable_days) if flt(encashable_days) > 0 else 0
            day_calculation = 360  # frappe.db.get_single_value("HR Settings", "day_calculation")
            if day_calculation == "Calendar":
                day_calculation = "365"
            day_percentage = 12 / flt(day_calculation)
            per_day_encashment = 0.0
            data = self.get_data_for_eval()
            salary_components = data["salary_components"]
            # frappe.msgprint(str(salary_components))
            for key in salary_components:
                check_add = frappe.db.get_value(
                    "Salary Component", key["salary_component"],
                    "include_in_leave_encashment_")
                if check_add == 1:
                    if key["amount_based_on_formula"] == 1 and key[
                            "amount_based_on_func"] == 0:
                        formula = key["formula"].strip(
                        ) if key["formula"] else None
                        if formula:
                            # frappe.msgprint(str(formula))
                            per_day_encashment += frappe.safe_eval(
                                formula, self.whitelisted_globals, data)
                    elif key["amount_based_on_func"] == 0:
                        per_day_encashment += flt(key["amount"])

                self.encashment_amount = self.encashable_days * day_percentage * per_day_encashment if per_day_encashment > 0 else 0
        else:
            self.encashment_amount = encashment_amount

        self.leave_allocation = self.get_leave_allocation()
        return True