def calculate_component_amounts(self): if not getattr(self, '_salary_structure_doc', None): self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure) data = self.get_data_for_eval() for key in ('earnings', 'deductions'): for struct_row in self._salary_structure_doc.get(key): amount = self.eval_condition_and_formula(struct_row, data) if amount and struct_row.statistical_component == 0: self.update_component_row(struct_row, amount, key) if key=="deductions" and struct_row.variable_based_on_taxable_salary: tax_row, amount = self.calculate_pro_rata_tax(struct_row.salary_component) if tax_row and amount: self.update_component_row(frappe._dict(tax_row), amount, key) additional_components = get_additional_salary_component(self.employee, self.start_date, self.end_date) if additional_components: for additional_component in additional_components: additional_component = frappe._dict(additional_component) 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 get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct, period_length, frequency): payroll_period, period_factor, actual_payroll_days = get_payroll_period_days( start_date, end_date, employee) if not payroll_period: frappe.msgprint( _("Start and end dates not in a valid Payroll Period, cannot calculate {0}." ).format(struct_row.salary_component)) return False # Considering there is only one application for a year benefit_application_name = frappe.db.sql( """ select name from `tabEmployee Benefit Application` where payroll_period=%(payroll_period)s and employee=%(employee)s and docstatus = 1 """, { 'employee': employee, 'payroll_period': payroll_period }) if frappe.db.get_value("Salary Component", struct_row.salary_component, "depends_on_payment_days") != 1: if frequency == "Monthly" and actual_payroll_days in range(360, 370): period_length = 1 period_factor = 12 if period_factor: # If there is application for benefit then fetch the amount from the application. # else Split the max benefits to the pro-rata components with the ratio of their max_benefit_amount if benefit_application_name: benefit_application = frappe.get_doc( "Employee Benefit Application", benefit_application_name[0][0]) return get_benefit_amount(benefit_application, struct_row, period_factor, period_length) # TODO: Check if there is benefit claim for employee then pro-rata divide the rest of amount (Late Benefit Application) else: component_max = frappe.db.get_value("Salary Component", struct_row.salary_component, "max_benefit_amount") if component_max: benefit_amount = get_benefit_pro_rata_ratio_amount( sal_struct, component_max) return get_amount(period_factor, benefit_amount, period_length) return False
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_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct, period_length, frequency): payroll_period, period_factor, actual_payroll_days = get_payroll_period_days(start_date, end_date, employee) if not payroll_period: frappe.msgprint(_("Start and end dates not in a valid Payroll Period, cannot calculate {0}.") .format(struct_row.salary_component)) return False # Considering there is only one application for a year benefit_application_name = frappe.db.sql(""" select name from `tabEmployee Benefit Application` where payroll_period=%(payroll_period)s and employee=%(employee)s and docstatus = 1 """, { 'employee': employee, 'payroll_period': payroll_period }) if frappe.db.get_value("Salary Component", struct_row.salary_component, "depends_on_payment_days") != 1: if frequency == "Monthly" and actual_payroll_days in range(360, 370): period_length = 1 period_factor = 12 if period_factor: # If there is application for benefit then fetch the amount from the application. # else Split the max benefits to the pro-rata components with the ratio of their max_benefit_amount if benefit_application_name: benefit_application = frappe.get_doc("Employee Benefit Application", benefit_application_name[0][0]) return get_benefit_amount(benefit_application, struct_row, period_factor, period_length) # TODO: Check if there is benefit claim for employee then pro-rata divide the rest of amount (Late Benefit Application) else: component_max = frappe.db.get_value("Salary Component", struct_row.salary_component, "max_benefit_amount") if component_max: benefit_amount = get_benefit_pro_rata_ratio_amount(sal_struct, component_max) return get_amount(period_factor, benefit_amount, period_length) return False
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 calculate_component_amounts(self): if not getattr(self, '_salary_structure_doc', None): self._salary_structure_doc = frappe.get_doc( 'Salary Structure', self.salary_structure) data = self.get_data_for_eval() for key in ('earnings', 'deductions'): for struct_row in self._salary_structure_doc.get(key): amount = self.eval_condition_and_formula(struct_row, data) if amount and struct_row.statistical_component == 0: self.update_component_row(struct_row, amount, key) if key == "deductions" and struct_row.variable_based_on_taxable_salary: tax_row, amount = self.calculate_pro_rata_tax( struct_row.salary_component) if tax_row and amount: self.update_component_row(frappe._dict(tax_row), amount, key) additional_components = get_additional_salary_component( self.employee, self.start_date, self.end_date) if additional_components: for additional_component in additional_components: additional_component = frappe._dict(additional_component) 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")