Skip to content

Commit

Permalink
Merge pull request #2311 from frappe/mergify/bp/version-15-hotfix/pr-…
Browse files Browse the repository at this point in the history
…2309

refactor(Salary Structure Assignment): opening balances setup warning + section visibility (backport #2309)
  • Loading branch information
ruchamahabal authored Oct 18, 2024
2 parents e34cd31 + 6185597 commit e224c6b
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 110 deletions.
14 changes: 3 additions & 11 deletions hrms/payroll/doctype/payroll_settings/payroll_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@
"encrypt_salary_slips_in_emails",
"password_policy",
"other_settings_section",
"define_opening_balance_for_earning_and_deductions",
"column_break_zi9y",
"process_payroll_accounting_entry_based_on_employee"
"process_payroll_accounting_entry_based_on_employee",
"column_break_zi9y"
],
"fields": [
{
Expand Down Expand Up @@ -112,13 +111,6 @@
"fieldname": "column_break_6",
"fieldtype": "Column Break"
},
{
"default": "0",
"description": "If checked, then the system will enable the provision to set the opening balance for earnings and deductions till date while creating a Salary Structure Assignment (if any)",
"fieldname": "define_opening_balance_for_earning_and_deductions",
"fieldtype": "Check",
"label": "Define Opening Balance for Earning and Deductions"
},
{
"fieldname": "column_break_rnoq",
"fieldtype": "Section Break",
Expand Down Expand Up @@ -186,7 +178,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-01-23 17:42:52.958013",
"modified": "2024-10-18 17:12:02.044020",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Payroll Settings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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", []);
}
Expand Down Expand Up @@ -143,30 +139,22 @@ 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");
},
});
},

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);
}
toggle_opening_balances_section: function (frm) {
if (!frm.doc.from_date || !frm.doc.employee) return;

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");
}
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"column_break_9",
"variable",
"amended_from",
"earnings_and_taxation_section",
"opening_balances_section",
"taxable_earnings_till_date",
"column_break_20",
"tax_deducted_till_date",
Expand Down Expand Up @@ -192,24 +192,25 @@
"fieldname": "column_break_20",
"fieldtype": "Column Break"
},
{
"collapsible_depends_on": "eval:doc.taxable_earnings_till_date && doc.tax_deducted_till_date",
"fieldname": "earnings_and_taxation_section",
"fieldtype": "Section Break",
"hidden": 1,
"label": "Earnings and Taxation "
},
{
"allow_on_submit": 1,
"fieldname": "taxable_earnings_till_date",
"fieldtype": "Currency",
"label": "Taxable Earnings Till Date",
"options": "currency"
},
{
"collapsible_depends_on": "eval:doc.taxable_earnings_till_date && doc.tax_deducted_till_date",
"description": "Set opening balances for earnings and taxes from the previous employer",
"fieldname": "opening_balances_section",
"fieldtype": "Section Break",
"hidden": 1,
"label": "Opening Balances"
}
],
"is_submittable": 1,
"links": [],
"modified": "2023-09-12 20:54:02.758373",
"modified": "2024-10-18 18:06:42.013701",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Structure Assignment",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,25 @@
from frappe.model.document import Document
from frappe.utils import cint, flt, get_link_to_form, getdate

from hrms.payroll.doctype.payroll_period.payroll_period import get_payroll_period


class DuplicateAssignment(frappe.ValidationError):
pass


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}. <br><br>
Please specify {1} and {2} (if any),
for the correct tax calculation in future salary slips.
"""
).format(
self.employee,
"<b>" + _("Taxable Earnings Till Date") + "</b>",
"<b>" + _("Tax Deducted Till Date") + "</b>",
),
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(
Expand Down Expand Up @@ -152,54 +130,52 @@ def validate_cost_center_distribution(self):
if total_percentage != 100:
frappe.throw(_("Total percentage against cost centers should be 100"))

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
):
msg = _("Could not find any salary slip(s) for the employee {0}").format(self.employee)
msg += "<br><br>"
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"),
)

@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
def are_opening_entries_required(self) -> bool:
if self.has_emp_joined_after_payroll_period_start() 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

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"
):
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})
def has_existing_salary_slips(self) -> bool:
return bool(
frappe.db.exists(
"Salary Slip",
{"employee": self.employee, "docstatus": 1},
)
)

if salary_slip:
def has_emp_joined_after_payroll_period_start(self) -> bool:
date_of_joining = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining"))
payroll_period = get_payroll_period(self.from_date, self.from_date, self.company)
if not payroll_period or date_of_joining > getdate(payroll_period.start_date):
return True

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"""

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:
return True

else:
return False


def get_assigned_salary_structure(employee, on_date):
if not employee or not on_date:
Expand Down

0 comments on commit e224c6b

Please sign in to comment.