mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-29 09:54:47 +00:00
feat: reverse linking and multiple additonal salaries in salary slip
This commit is contained in:
@@ -9,6 +9,13 @@ from frappe import _
|
|||||||
from frappe.utils import getdate, date_diff
|
from frappe.utils import getdate, date_diff
|
||||||
|
|
||||||
class AdditionalSalary(Document):
|
class AdditionalSalary(Document):
|
||||||
|
|
||||||
|
def on_submit(self):
|
||||||
|
if self.ref_doctype == "Employee Advance" and self.ref_docname:
|
||||||
|
emp_adv = frappe.get_doc(self.ref_doctype, self.ref_docname)
|
||||||
|
emp_adv.return_amount = self.amount
|
||||||
|
emp_adv.save()
|
||||||
|
|
||||||
def before_insert(self):
|
def before_insert(self):
|
||||||
if frappe.db.exists("Additional Salary", {"employee": self.employee, "salary_component": self.salary_component,
|
if frappe.db.exists("Additional Salary", {"employee": self.employee, "salary_component": self.salary_component,
|
||||||
"amount": self.amount, "payroll_date": self.payroll_date, "company": self.company, "docstatus": 1}):
|
"amount": self.amount, "payroll_date": self.payroll_date, "company": self.company, "docstatus": 1}):
|
||||||
@@ -49,8 +56,8 @@ class AdditionalSalary(Document):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_additional_salary_component(employee, start_date, end_date, component_type):
|
def get_additional_salary_component(employee, start_date, end_date, component_type):
|
||||||
additional_components = frappe.db.sql("""
|
additional_salaries = frappe.db.sql("""
|
||||||
select name, salary_component, amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date
|
select name, salary_component, type, amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date
|
||||||
from `tabAdditional Salary`
|
from `tabAdditional Salary`
|
||||||
where employee=%(employee)s
|
where employee=%(employee)s
|
||||||
and docstatus = 1
|
and docstatus = 1
|
||||||
@@ -60,7 +67,7 @@ def get_additional_salary_component(employee, start_date, end_date, component_ty
|
|||||||
from_date <= %(to_date)s and to_date >= %(to_date)s
|
from_date <= %(to_date)s and to_date >= %(to_date)s
|
||||||
)
|
)
|
||||||
and type = %(component_type)s
|
and type = %(component_type)s
|
||||||
order by salary_component, overwrite_salary_structure_amount
|
order by salary_component, overwrite_salary_structure_amount DESC
|
||||||
""", {
|
""", {
|
||||||
'employee': employee,
|
'employee': employee,
|
||||||
'from_date': start_date,
|
'from_date': start_date,
|
||||||
@@ -68,26 +75,38 @@ def get_additional_salary_component(employee, start_date, end_date, component_ty
|
|||||||
'component_type': "Earning" if component_type == "earnings" else "Deduction"
|
'component_type': "Earning" if component_type == "earnings" else "Deduction"
|
||||||
}, as_dict=1)
|
}, as_dict=1)
|
||||||
|
|
||||||
additional_components_list = []
|
existing_salary_components= []
|
||||||
existing_salary_components = []
|
salary_components_details = {}
|
||||||
|
additional_salary_details = []
|
||||||
|
|
||||||
|
overwrites_components = [ele.salary_component for ele in additional_salaries if ele.overwrite_salary_structure_amount == 1]
|
||||||
|
|
||||||
component_fields = ["depends_on_payment_days", "salary_component_abbr", "is_tax_applicable", "variable_based_on_taxable_salary", 'type']
|
component_fields = ["depends_on_payment_days", "salary_component_abbr", "is_tax_applicable", "variable_based_on_taxable_salary", 'type']
|
||||||
for d in additional_components:
|
for d in additional_salaries:
|
||||||
if d.salary_component in existing_salary_components:
|
|
||||||
frappe.throw(_('Multiple additional Salary is created for Salary Component {0}'.format(d.salary_component)))
|
|
||||||
struct_row = frappe._dict({'salary_component': d.salary_component})
|
|
||||||
component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields)
|
|
||||||
if component:
|
|
||||||
struct_row.update(component[0])
|
|
||||||
|
|
||||||
struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date
|
if d.salary_component not in existing_salary_components:
|
||||||
struct_row['is_additional_component'] = 1
|
component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields)
|
||||||
struct_row['additional_salary'] = d.name
|
struct_row = frappe._dict({'salary_component': d.salary_component})
|
||||||
|
if component:
|
||||||
|
struct_row.update(component[0])
|
||||||
|
|
||||||
|
struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date
|
||||||
|
struct_row['is_additional_component'] = 1
|
||||||
|
|
||||||
|
salary_components_details[d.salary_component] = struct_row
|
||||||
|
|
||||||
|
|
||||||
|
if overwrites_components.count(d.salary_component) > 1:
|
||||||
|
frappe.throw(_("Multiple Additional Salaries with overwrite property exist for Salary Component: {0} between {1} and {2}.".format(d.salary_component, start_date, end_date)), title=_("Error"))
|
||||||
|
else:
|
||||||
|
additional_salary_details.append({
|
||||||
|
'name': d.name,
|
||||||
|
'component': d.salary_component,
|
||||||
|
'amount': d.amount,
|
||||||
|
'type': d.type,
|
||||||
|
'overwrite': d.overwrite_salary_structure_amount,
|
||||||
|
})
|
||||||
|
|
||||||
additional_components_list.append(frappe._dict({
|
|
||||||
'amount': d.amount,
|
|
||||||
'type': component[0].type,
|
|
||||||
'struct_row': struct_row,
|
|
||||||
'overwrite': d.overwrite_salary_structure_amount,
|
|
||||||
}))
|
|
||||||
existing_salary_components.append(d.salary_component)
|
existing_salary_components.append(d.salary_component)
|
||||||
return additional_components_list
|
|
||||||
|
return salary_components_details, additional_salary_details
|
||||||
@@ -165,6 +165,7 @@
|
|||||||
"options": "Mode of Payment"
|
"options": "Mode of Payment"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "return_amount",
|
"fieldname": "return_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Returned Amount",
|
"label": "Returned Amount",
|
||||||
@@ -180,7 +181,7 @@
|
|||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-05 16:31:50.417539",
|
"modified": "2020-03-06 15:11:33.747535",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee Advance",
|
"name": "Employee Advance",
|
||||||
|
|||||||
@@ -9,27 +9,13 @@ from frappe.model.document import Document
|
|||||||
class EmployeeIncentive(Document):
|
class EmployeeIncentive(Document):
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
company = frappe.db.get_value('Employee', self.employee, 'company')
|
company = frappe.db.get_value('Employee', self.employee, 'company')
|
||||||
additional_salary = frappe.db.exists('Additional Salary', {
|
|
||||||
'employee': self.employee,
|
|
||||||
'ref_doctype': self.doctype,
|
|
||||||
'ref_docname': self.name,
|
|
||||||
'salary_component': self.salary_component,
|
|
||||||
'payroll_date': self.payroll_date,
|
|
||||||
'company': company,
|
|
||||||
'docstatus': ["!=", 2]
|
|
||||||
})
|
|
||||||
|
|
||||||
if not additional_salary:
|
|
||||||
additional_salary = frappe.new_doc('Additional Salary')
|
|
||||||
additional_salary.employee = self.employee
|
|
||||||
additional_salary.salary_component = self.salary_component
|
|
||||||
additional_salary.amount = self.incentive_amount
|
|
||||||
additional_salary.payroll_date = self.payroll_date
|
|
||||||
additional_salary.company = company
|
|
||||||
additional_salary.ref_doctype = self.doctype
|
|
||||||
additional_salary.ref_docname = self.name
|
|
||||||
additional_salary.submit()
|
|
||||||
else:
|
|
||||||
incentive_added = frappe.db.get_value('Additional Salary', additional_salary, 'amount') + self.incentive_amount
|
|
||||||
frappe.db.set_value('Additional Salary', additional_salary, {'amount', incentive_added})
|
|
||||||
|
|
||||||
|
additional_salary = frappe.new_doc('Additional Salary')
|
||||||
|
additional_salary.employee = self.employee
|
||||||
|
additional_salary.salary_component = self.salary_component
|
||||||
|
additional_salary.amount = self.incentive_amount
|
||||||
|
additional_salary.payroll_date = self.payroll_date
|
||||||
|
additional_salary.company = company
|
||||||
|
additional_salary.ref_doctype = self.doctype
|
||||||
|
additional_salary.ref_docname = self.name
|
||||||
|
additional_salary.submit()
|
||||||
|
|||||||
@@ -31,13 +31,16 @@ class LeaveEncashment(Document):
|
|||||||
additional_salary = frappe.new_doc("Additional Salary")
|
additional_salary = frappe.new_doc("Additional Salary")
|
||||||
additional_salary.company = frappe.get_value("Employee", self.employee, "company")
|
additional_salary.company = frappe.get_value("Employee", self.employee, "company")
|
||||||
additional_salary.employee = self.employee
|
additional_salary.employee = self.employee
|
||||||
additional_salary.salary_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
|
earning_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
|
||||||
|
if not earning_component:
|
||||||
|
frappe.throw(_("Please set Earning Component for Leave type: {0}.".format(self.leave_type)))
|
||||||
|
additional_salary.salary_component = earning_component
|
||||||
additional_salary.payroll_date = self.encashment_date
|
additional_salary.payroll_date = self.encashment_date
|
||||||
additional_salary.amount = self.encashment_amount
|
additional_salary.amount = self.encashment_amount
|
||||||
|
additional_salary.ref_doctype = self.doctype
|
||||||
|
additional_salary.ref_docname = self.name
|
||||||
additional_salary.submit()
|
additional_salary.submit()
|
||||||
|
|
||||||
self.db_set("additional_salary", additional_salary.name)
|
|
||||||
|
|
||||||
# Set encashed leaves in Allocation
|
# Set encashed leaves in Allocation
|
||||||
frappe.db.set_value("Leave Allocation", self.leave_allocation, "total_leaves_encashed",
|
frappe.db.set_value("Leave Allocation", self.leave_allocation, "total_leaves_encashed",
|
||||||
frappe.db.get_value('Leave Allocation', self.leave_allocation, 'total_leaves_encashed') + self.encashable_days)
|
frappe.db.get_value('Leave Allocation', self.leave_allocation, 'total_leaves_encashed') + self.encashable_days)
|
||||||
@@ -119,4 +122,4 @@ def create_leave_encashment(leave_allocation):
|
|||||||
leave_type=allocation.leave_type,
|
leave_type=allocation.leave_type,
|
||||||
encashment_date=allocation.to_date
|
encashment_date=allocation.to_date
|
||||||
))
|
))
|
||||||
leave_encashment.insert(ignore_permissions=True)
|
leave_encashment.insert(ignore_permissions=True)
|
||||||
@@ -74,7 +74,6 @@ class SalarySlip(TransactionBase):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.set_status()
|
self.set_status()
|
||||||
self.update_status()
|
self.update_status()
|
||||||
self.update_salary_slip_in_additional_salary()
|
|
||||||
self.cancel_loan_repayment_entry()
|
self.cancel_loan_repayment_entry()
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
@@ -405,14 +404,15 @@ class SalarySlip(TransactionBase):
|
|||||||
self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings")
|
self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings")
|
||||||
|
|
||||||
def add_additional_salary_components(self, component_type):
|
def add_additional_salary_components(self, component_type):
|
||||||
additional_components = get_additional_salary_component(self.employee,
|
salary_components_details, additional_salary_details = get_additional_salary_component(self.employee,
|
||||||
self.start_date, self.end_date, component_type)
|
self.start_date, self.end_date, component_type)
|
||||||
if additional_components:
|
if salary_components_details and additional_salary_details:
|
||||||
for additional_component in additional_components:
|
for additional_salary in additional_salary_details:
|
||||||
amount = additional_component.amount
|
additional_salary =frappe._dict(additional_salary)
|
||||||
overwrite = additional_component.overwrite
|
amount = additional_salary.amount
|
||||||
self.update_component_row(frappe._dict(additional_component.struct_row), amount,
|
overwrite = additional_salary.overwrite
|
||||||
component_type, overwrite=overwrite)
|
self.update_component_row(frappe._dict(salary_components_details[additional_salary.component]), amount,
|
||||||
|
component_type, overwrite=overwrite, additional_salary=additional_salary.name)
|
||||||
|
|
||||||
def add_tax_components(self, payroll_period):
|
def add_tax_components(self, payroll_period):
|
||||||
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
|
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
|
||||||
@@ -432,21 +432,20 @@ class SalarySlip(TransactionBase):
|
|||||||
tax_row = self.get_salary_slip_row(d)
|
tax_row = self.get_salary_slip_row(d)
|
||||||
self.update_component_row(tax_row, tax_amount, "deductions")
|
self.update_component_row(tax_row, tax_amount, "deductions")
|
||||||
|
|
||||||
def update_component_row(self, struct_row, amount, key, overwrite=1):
|
def update_component_row(self, struct_row, amount, key, overwrite=1, additional_salary = ''):
|
||||||
component_row = None
|
component_row = None
|
||||||
for d in self.get(key):
|
for d in self.get(key):
|
||||||
if d.salary_component == struct_row.salary_component:
|
if d.salary_component == struct_row.salary_component:
|
||||||
component_row = d
|
component_row = d
|
||||||
|
if not component_row or (struct_row.get("is_additional_component") and not overwrite):
|
||||||
if not component_row:
|
|
||||||
if amount:
|
if amount:
|
||||||
self.append(key, {
|
self.append(key, {
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
'additional_salary': '' if not struct_row.get("additional_salary") else struct_row.get("additional_salary"),
|
|
||||||
'default_amount': amount if not struct_row.get("is_additional_component") else 0,
|
'default_amount': amount if not struct_row.get("is_additional_component") else 0,
|
||||||
'depends_on_payment_days' : struct_row.depends_on_payment_days,
|
'depends_on_payment_days' : struct_row.depends_on_payment_days,
|
||||||
'salary_component' : struct_row.salary_component,
|
'salary_component' : struct_row.salary_component,
|
||||||
'abbr' : struct_row.abbr,
|
'abbr' : struct_row.abbr,
|
||||||
|
'additional_salary': additional_salary,
|
||||||
'do_not_include_in_total' : struct_row.do_not_include_in_total,
|
'do_not_include_in_total' : struct_row.do_not_include_in_total,
|
||||||
'is_tax_applicable': struct_row.is_tax_applicable,
|
'is_tax_applicable': struct_row.is_tax_applicable,
|
||||||
'is_flexible_benefit': struct_row.is_flexible_benefit,
|
'is_flexible_benefit': struct_row.is_flexible_benefit,
|
||||||
@@ -458,6 +457,7 @@ class SalarySlip(TransactionBase):
|
|||||||
if struct_row.get("is_additional_component"):
|
if struct_row.get("is_additional_component"):
|
||||||
if overwrite:
|
if overwrite:
|
||||||
component_row.additional_amount = amount - component_row.get("default_amount", 0)
|
component_row.additional_amount = amount - component_row.get("default_amount", 0)
|
||||||
|
component_row.additional_salary = additional_salary
|
||||||
else:
|
else:
|
||||||
component_row.additional_amount = amount
|
component_row.additional_amount = amount
|
||||||
|
|
||||||
@@ -878,4 +878,4 @@ def unlink_ref_doc_from_salary_slip(ref_no):
|
|||||||
|
|
||||||
def generate_password_for_pdf(policy_template, employee):
|
def generate_password_for_pdf(policy_template, employee):
|
||||||
employee = frappe.get_doc("Employee", employee)
|
employee = frappe.get_doc("Employee", employee)
|
||||||
return policy_template.format(**employee.as_dict())
|
return policy_template.format(**employee.as_dict())
|
||||||
Reference in New Issue
Block a user