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):