diff --git a/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js b/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js index 4deee7e3db..1658171c68 100644 --- a/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js +++ b/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js @@ -53,11 +53,7 @@ frappe.ui.form.on("Salary Structure Assignment", { }, refresh: function (frm) { - if (frm.doc.__onload) { - frm.unhide_earnings_and_taxation_section = - frm.doc.__onload.earning_and_deduction_entries_does_not_exists; - frm.trigger("set_earnings_and_taxation_section_visibility"); - } + frm.trigger("toggle_opening_balances_section"); if (frm.doc.docstatus != 1) return; @@ -85,7 +81,7 @@ frappe.ui.form.on("Salary Structure Assignment", { employee: function (frm) { if (frm.doc.employee) { frm.trigger("set_payroll_cost_centers"); - frm.trigger("valiadte_joining_date_and_salary_slips"); + frm.trigger("toggle_opening_balances_section"); } else { frm.set_value("payroll_cost_centers", []); } @@ -144,30 +140,21 @@ frappe.ui.form.on("Salary Structure Assignment", { } }, - valiadte_joining_date_and_salary_slips: function (frm) { - frappe.call({ - method: "earning_and_deduction_entries_does_not_exists", - doc: frm.doc, - callback: function (data) { - let earning_and_deduction_entries_does_not_exists = data.message; - frm.unhide_earnings_and_taxation_section = - earning_and_deduction_entries_does_not_exists; - frm.trigger("set_earnings_and_taxation_section_visibility"); - }, - }); - }, + toggle_opening_balances_section: function (frm) { + if (!frm.doc.from_date || !frm.doc.employee) return; - set_earnings_and_taxation_section_visibility: function (frm) { - if (frm.unhide_earnings_and_taxation_section) { - frm.set_df_property("earnings_and_taxation_section", "hidden", 0); - } else { - frm.set_df_property("earnings_and_taxation_section", "hidden", 1); - } + frm.call("are_opening_entries_required").then((data) => { + if (data.message) { + frm.set_df_property("opening_balances_section", "hidden", 0); + } else { + frm.set_df_property("opening_balances_section", "hidden", 1); + } + }); }, from_date: function (frm) { if (frm.doc.from_date) { - frm.trigger("valiadte_joining_date_and_salary_slips"); + frm.trigger("toggle_opening_balances_section"); } }, }); diff --git a/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py b/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py index 48aad837e5..d462c3042c 100644 --- a/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py +++ b/hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py @@ -13,41 +13,17 @@ class DuplicateAssignment(frappe.ValidationError): class SalaryStructureAssignment(Document): - def onload(self): - if self.employee: - self.set_onload( - "earning_and_deduction_entries_does_not_exists", - self.earning_and_deduction_entries_does_not_exists(), - ) - def validate(self): self.validate_dates() self.validate_company() self.validate_income_tax_slab() self.set_payroll_payable_account() - if self.earning_and_deduction_entries_does_not_exists(): - if not self.taxable_earnings_till_date and not self.tax_deducted_till_date: - frappe.msgprint( - _( - """ - Not found any salary slip record(s) for the employee {0}.

- Please specify {1} and {2} (if any), - for the correct tax calculation in future salary slips. - """ - ).format( - self.employee, - "" + _("Taxable Earnings Till Date") + "", - "" + _("Tax Deducted Till Date") + "", - ), - indicator="orange", - title=_("Warning"), - ) - if not self.get("payroll_cost_centers"): self.set_payroll_cost_centers() self.validate_cost_center_distribution() + self.warn_about_missing_opening_entries() def validate_dates(self): joining_date, relieving_date = frappe.db.get_value( @@ -152,53 +128,57 @@ def validate_cost_center_distribution(self): if total_percentage != 100: frappe.throw(_("Total percentage against cost centers should be 100")) - @frappe.whitelist() - def earning_and_deduction_entries_does_not_exists(self): - if self.enabled_settings_to_specify_earnings_and_deductions_till_date(): - if not self.joined_in_the_same_month() and not self.have_salary_slips(): - return True - else: - if self.docstatus in [1, 2] and ( - self.taxable_earnings_till_date or self.tax_deducted_till_date - ): - return True - return False - else: - return False - - def enabled_settings_to_specify_earnings_and_deductions_till_date(self): - """returns True if settings are enabled to specify earnings and deductions till date else False""" - - if frappe.db.get_single_value( - "Payroll Settings", "define_opening_balance_for_earning_and_deductions" + def warn_about_missing_opening_entries(self): + if ( + self.are_opening_entries_required() + and not self.taxable_earnings_till_date + and not self.tax_deducted_till_date ): - return True - return False - - def have_salary_slips(self): - """returns True if salary structure assignment has salary slips else False""" - - salary_slip = frappe.db.get_value("Salary Slip", filters={"employee": self.employee, "docstatus": 1}) + msg = _("Could not find any salary slip(s) for the employee {0}").format(self.employee) + msg += "

" + msg += _( + "Please specify {0} and {1} (if any), for the correct tax calculation in future salary slips." + ).format( + frappe.bold(_("Taxable Earnings Till Date")), + frappe.bold(_("Tax Deducted Till Date")), + ) + frappe.msgprint( + msg, + indicator="orange", + title=_("Missing Opening Entries"), + ) - if salary_slip: + @frappe.whitelist() + def are_opening_entries_required(self) -> bool: + if not self.emp_joined_in_the_same_month() and not self.has_existing_salary_slips(): return True + else: + if not self.docstatus.is_draft() and ( + self.taxable_earnings_till_date or self.tax_deducted_till_date + ): + return True + return False - return False - - def joined_in_the_same_month(self): - """returns True if employee joined in same month as salary structure assignment from date else False""" + def has_existing_salary_slips(self) -> bool: + return bool( + frappe.db.exists( + "Salary Slip", + {"employee": self.employee, "docstatus": 1}, + ) + ) + def emp_joined_in_the_same_month(self) -> bool: date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining") from_date = getdate(self.from_date) - if not self.from_date or not date_of_joining: - return False - - elif date_of_joining.month == from_date.month: + if ( + self.from_date + and date_of_joining + and date_of_joining.month == from_date.month + and date_of_joining.year == from_date.year + ): return True - - else: - return False + return False def get_assigned_salary_structure(employee, on_date):