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 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 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
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 get_earning_components_max_benefits(employee, date, earning_component): salary_structure = get_assigned_salary_structure(employee, date) amount = frappe.db.sql(""" select amount from `tabSalary Detail` where parent = %s and is_flexible_benefit = 1 and salary_component = %s order by name """, salary_structure, earning_component) return amount if amount else 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 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)[1] 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_amount_based_on_pro_rata( 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): 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 # adding this because the function returns a -ve number + get_leaves_for_period(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