mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-09 00:01:18 +00:00
feat: Validation, sider and form dashbord
This commit is contained in:
@@ -45,15 +45,21 @@ frappe.ui.form.on('Attendance', {
|
||||
},
|
||||
|
||||
set_overtime_type: function(frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.hr.doctype.attendance.attendance.get_overtime_type",
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frm.set_value("overtime_type", r.message);
|
||||
}
|
||||
frappe.db.get_single_value("Payroll Settings", "overtime_based_on").then((r)=>{
|
||||
if (r == "Attendance") {
|
||||
frappe.call({
|
||||
method: "erpnext.hr.doctype.attendance.attendance.get_overtime_type",
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frm.set_value("overtime_type", r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frm.set_value("overtime_type", '');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import getdate, nowdate
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from erpnext.hr.utils import validate_active_employee
|
||||
from frappe.utils import cstr, get_datetime, formatdate, getdate
|
||||
from frappe.utils import cstr, get_datetime, formatdate, getdate, nowdate
|
||||
|
||||
class Attendance(Document):
|
||||
def validate(self):
|
||||
@@ -58,7 +57,7 @@ class Attendance(Document):
|
||||
self.overtime_type = get_overtime_type(self.employee)
|
||||
|
||||
if self.overtime_type:
|
||||
if frappe.db.get_single_value("Payroll Settings", "overtime_based_on") != "Attendance":
|
||||
if frappe.db.get_single_value("Payroll Settings", "overtime_based_on") != "Attendance":
|
||||
frappe.msgprint(_('Set "Calculate Overtime Based On Attendance" to Attendance for Overtime Slip Creation'))
|
||||
|
||||
maximum_overtime_hours_allowed = frappe.db.get_single_value("Payroll Settings", "maximum_overtime_hours_allowed")
|
||||
@@ -136,25 +135,28 @@ def get_shift_type(employee, attendance_date):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_overtime_type(employee):
|
||||
emp_department = frappe.db.get_value("Employee", employee, "department")
|
||||
if emp_department:
|
||||
overtime_type = frappe.get_list("Overtime Type", filters={"party_type": "Department", "party": emp_department}, fields=['name'])
|
||||
if len(overtime_type):
|
||||
overtime_type = overtime_type[0].name
|
||||
|
||||
emp_grade = frappe.db.get_value("Employee", employee, "grade")
|
||||
if emp_grade:
|
||||
overtime_type = frappe.get_list("Overtime Type", filters={"party_type": "Employee Grade", "party": emp_grade},
|
||||
fields=['name'])
|
||||
if len(overtime_type):
|
||||
|
||||
overtime_type = overtime_type[0].name
|
||||
|
||||
overtime_type = frappe.get_list("Overtime Type", filters={"party_type": "Employee", "party": employee}, fields=['name'])
|
||||
emp_department = frappe.db.get_value("Employee", employee, "department")
|
||||
if emp_department:
|
||||
overtime_type = frappe.get_list("Overtime Type", filters={
|
||||
"applicable_for": "Department", "department": emp_department}, fields=['name'])
|
||||
if len(overtime_type):
|
||||
overtime_type = overtime_type[0].name
|
||||
|
||||
return overtime_type
|
||||
emp_grade = frappe.db.get_value("Employee", employee, "grade")
|
||||
if emp_grade:
|
||||
overtime_type = frappe.get_list("Overtime Type", filters={
|
||||
"applicable_for": "Employee Grade", "employee_grade": emp_grade},
|
||||
fields=['name'])
|
||||
if len(overtime_type):
|
||||
|
||||
overtime_type = overtime_type[0].name
|
||||
|
||||
overtime_type = frappe.get_list("Overtime Type", filters={
|
||||
"applicable_for": "Employee", "employee": employee}, fields=['name'])
|
||||
if len(overtime_type):
|
||||
overtime_type = overtime_type[0].name
|
||||
|
||||
return overtime_type
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_events(start, end, filters=None):
|
||||
|
||||
@@ -42,11 +42,11 @@ class EmployeeCheckin(Document):
|
||||
self.shift_start = shift_actual_timings[2].start_datetime
|
||||
self.shift_end = shift_actual_timings[2].end_datetime
|
||||
elif frappe.db.get_value("Shift Type", shift_actual_timings[2].shift_type.name, "allow_overtime"):
|
||||
#because after Actual time it takes check-in/out invalid
|
||||
#if employee checkout late or check-in before before shift timing adding time buffer.
|
||||
self.shift = shift_actual_timings[2].shift_type.name
|
||||
self.shift_start = shift_actual_timings[2].start_datetime
|
||||
self.shift_end = shift_actual_timings[2].end_datetime
|
||||
#because after Actual time it takes check-in/out invalid
|
||||
#if employee checkout late or check-in before before shift timing adding time buffer.
|
||||
self.shift = shift_actual_timings[2].shift_type.name
|
||||
self.shift_start = shift_actual_timings[2].start_datetime
|
||||
self.shift_end = shift_actual_timings[2].end_datetime
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_log_based_on_employee_field(employee_field_value, timestamp, device_id=None, log_type=None, skip_auto_attendance=0, employee_fieldname='attendance_device_id'):
|
||||
|
||||
@@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, cstr, getdate, now_datetime, nowdate
|
||||
from frappe.utils import cstr, getdate, now_datetime, nowdate
|
||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||
from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
|
||||
from erpnext.hr.utils import validate_active_employee
|
||||
@@ -61,12 +61,12 @@ class ShiftAssignment(Document):
|
||||
def throw_overlap_error(self, shift_details):
|
||||
shift_details = frappe._dict(shift_details)
|
||||
if shift_details.docstatus == 1 and shift_details.status == "Active":
|
||||
msg = _("Employee {0} already has Active Shift {1}: {2}").format(frappe.bold(self.employee), frappe.bold(self.shift_type), frappe.bold(shift_details.name))
|
||||
msg = _("Employee {0} already has Active Shift {1}: {2}").format(frappe.bold(self.employee), frappe.bold(self.shift_type), frappe.bold(shift_details.name)) + " "
|
||||
if shift_details.start_date:
|
||||
msg += _(" from {0}").format(getdate(self.start_date).strftime("%d-%m-%Y"))
|
||||
msg += _("from {0}").format(getdate(self.start_date).strftime("%d-%m-%Y")) + " "
|
||||
title = "Ongoing Shift"
|
||||
if shift_details.end_date:
|
||||
msg += _(" to {0}").format(getdate(self.end_date).strftime("%d-%m-%Y"))
|
||||
msg += _("to {0}").format(getdate(self.end_date).strftime("%d-%m-%Y"))
|
||||
title = "Active Shift"
|
||||
if msg:
|
||||
frappe.throw(msg, title=title)
|
||||
@@ -273,7 +273,7 @@ def get_actual_start_end_datetime_of_shift(employee, for_datetime, consider_defa
|
||||
if timestamp and for_datetime <= timestamp:
|
||||
timestamp_index = index
|
||||
break
|
||||
if timestamp_index and timestamp_index%2 == 1:
|
||||
if timestamp_index and timestamp_index % 2 == 1:
|
||||
shift_details = shift_timings_as_per_timestamp[int((timestamp_index-1)/2)]
|
||||
actual_shift_start = shift_details.actual_start
|
||||
actual_shift_end = shift_details.actual_end
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"column_break_19",
|
||||
"process_attendance_after",
|
||||
"last_sync_of_checkin",
|
||||
"grace_period_settings_auto_attendance_section",
|
||||
"grace_period_settings_section",
|
||||
"enable_entry_grace_period",
|
||||
"late_entry_grace_period",
|
||||
"column_break_18",
|
||||
@@ -141,12 +141,6 @@
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Auto Attendance Settings"
|
||||
},
|
||||
{
|
||||
"depends_on": "enable_auto_attendance",
|
||||
"fieldname": "grace_period_settings_auto_attendance_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Grace Period Settings For Auto Attendance"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Mark attendance based on 'Employee Checkin' for Employees assigned to this shift.",
|
||||
@@ -188,10 +182,16 @@
|
||||
{
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "enable_auto_attendance",
|
||||
"fieldname": "grace_period_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Grace Period Settings"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2021-06-09 13:38:25.697100",
|
||||
"modified": "2021-06-15 15:22:55.756078",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Shift Type",
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import itertools
|
||||
from datetime import timedelta
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from math import modf
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, getdate, get_datetime
|
||||
from erpnext.hr.doctype.shift_assignment.shift_assignment import get_actual_start_end_datetime_of_shift, get_employee_shift
|
||||
@@ -26,7 +23,7 @@ class ShiftType(Document):
|
||||
end_time = self.end_time.split(":")
|
||||
start_time = self.start_time.split(":")
|
||||
|
||||
shift_end = timedelta(hours = int(end_time[0]), minutes = int(end_time[1]), seconds = int(end_time[2]))
|
||||
shift_end = timedelta(hours = int(end_time[0]), minutes = int(end_time[1]), seconds = int(end_time[2]))
|
||||
shift_start = timedelta(hours =int(start_time[0]), minutes = int(start_time[1]), seconds = int(start_time[2]))
|
||||
|
||||
if shift_end > shift_start:
|
||||
|
||||
@@ -10,7 +10,10 @@ def get_data():
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Attendance', 'Employee Checkin', 'Shift Request', 'Shift Assignment']
|
||||
'items': ['Attendance', 'Employee Checkin']
|
||||
},
|
||||
{
|
||||
'items': ['Shift Request', 'Shift Assignment']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ def get_gratuity_rule_slabs(gratuity_rule):
|
||||
return frappe.get_all("Gratuity Rule Slab", filters= {'parent': gratuity_rule}, fields = ["*"], order_by="idx")
|
||||
|
||||
def get_salary_structure(employee):
|
||||
salary_structure_assignment = frappe.get_list("Salary Structure Assignment", filters = {
|
||||
salary_structure_assignment = frappe.get_list("Salary Structure Assignment", filters = {
|
||||
"employee": employee, 'docstatus': 1
|
||||
},
|
||||
fields=["from_date", "salary_structure"],
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"to_date",
|
||||
"column_break_10",
|
||||
"payroll_frequency",
|
||||
"salary_slip",
|
||||
"section_break_12",
|
||||
"overtime_details",
|
||||
"section_break_13",
|
||||
@@ -134,12 +135,20 @@
|
||||
"fieldtype": "Date",
|
||||
"label": "Posting Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "salary_slip",
|
||||
"fieldtype": "Link",
|
||||
"label": "Salary Slip",
|
||||
"options": "Salary Slip",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-06-10 13:35:57.511257",
|
||||
"modified": "2021-06-15 12:53:17.355755",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Overtime Slip",
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from erpnext.hr.doctype.attendance.attendance import get_overtime_type
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import get_datetime, getdate
|
||||
from frappe import _, bold
|
||||
from frappe.utils import get_datetime, getdate, get_link_to_form, formatdate
|
||||
from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_start_end_dates
|
||||
from erpnext.payroll.doctype.gratuity.gratuity import get_salary_structure
|
||||
from frappe.model.document import Document
|
||||
class OvertimeSlip(Document):
|
||||
def validate(self):
|
||||
self.validate_overlap()
|
||||
if self.from_date >= self.to_date:
|
||||
frappe.throw(_("From date can not be greater than To date"))
|
||||
|
||||
if not (self.from_date or self.to_date or self.payroll_frequency):
|
||||
date = self.from_date or self.posting_date
|
||||
get_frequency_and_dates(self.employee, date)
|
||||
|
||||
if not len(self.overtime_details):
|
||||
self.get_emp_and_overtime_details()
|
||||
|
||||
def validate_overlap(self):
|
||||
if not self.name:
|
||||
# hack! if name is null, it could cause problems with !=
|
||||
self.name = "new-overtime-slip-1"
|
||||
|
||||
overtime_slips = frappe.db.get_all("Overtime Slip", filters = {
|
||||
"docstatus": ("<", 2),
|
||||
"employee": self.employee,
|
||||
"to_date": (">=", self.from_date),
|
||||
"from_date": ("<=", self.to_date)
|
||||
})
|
||||
if len(overtime_slips):
|
||||
form_link = get_link_to_form("Overtime Slip", overtime_slips[0].name)
|
||||
msg = _("Overtime Slip:{0} has been created between {1} and {1}").format(
|
||||
bold(form_link),
|
||||
bold(formatdate(self.from_date)), bold(formatdate(self.to_date)))
|
||||
frappe.throw(msg)
|
||||
|
||||
def on_submit(self):
|
||||
if self.status == "Pending":
|
||||
frappe.throw(_("Overtime Slip with Status 'Approved' or 'Rejected' are allowed for Submission"))
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
frappe.ui.form.on('Overtime Type', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("party_type", () => {
|
||||
let party_type = ["Employee", "Department", "Employee Grade"];
|
||||
frm.set_query("applicable_for", () => {
|
||||
let doctype_list = ["Employee", "Department", "Employee Grade"];
|
||||
return {
|
||||
filters: {
|
||||
name: ["in", party_type]
|
||||
name: ["in", doctype_list]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"party_type",
|
||||
"party",
|
||||
"applicable_for",
|
||||
"employee",
|
||||
"department",
|
||||
"employee_grade",
|
||||
"column_break_3",
|
||||
"applicable_salary_component",
|
||||
"pay_rate_multipliers_section",
|
||||
@@ -19,20 +21,6 @@
|
||||
"public_holiday_multiplier"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "party_type",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Party Type",
|
||||
"options": "DocType",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "party",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Party",
|
||||
"options": "party_type"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
@@ -41,7 +29,8 @@
|
||||
"fieldname": "applicable_salary_component",
|
||||
"fieldtype": "Table MultiSelect",
|
||||
"label": "Applicable Salary Component",
|
||||
"options": "Overtime Salary Component"
|
||||
"options": "Overtime Salary Component",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"description": "Pay Rate Multipliers apply to the hourly wage for the position you\u2019re working during the overtime hours.",
|
||||
@@ -87,11 +76,43 @@
|
||||
"fieldtype": "Float",
|
||||
"label": "Public Holiday Multiplier",
|
||||
"mandatory_depends_on": "eval: doc.applicable_for_public_holiday == 1"
|
||||
},
|
||||
{
|
||||
"fieldname": "applicable_for",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Applicable For",
|
||||
"options": "DocType",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.applicable_for == \"Employee\"",
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"label": "Employee",
|
||||
"mandatory_depends_on": "eval: doc.applicable_for == \"Employee\"",
|
||||
"options": "Employee"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.applicable_for == \"Department\"",
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"label": "Department",
|
||||
"mandatory_depends_on": "eval: doc.applicable_for == \"Department\"",
|
||||
"options": "Department"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.applicable_for == \"Employee Grade\"",
|
||||
"fieldname": "employee_grade",
|
||||
"fieldtype": "Link",
|
||||
"label": "Employee Grade",
|
||||
"mandatory_depends_on": "eval: doc.applicable_for == \"Employee Grade\"",
|
||||
"options": "Employee Grade"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-06-09 15:43:43.891270",
|
||||
"modified": "2021-06-15 13:49:20.612464",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Overtime Type",
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'overtime_type',
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Attendance', 'Timesheet']
|
||||
},
|
||||
{
|
||||
'items': ['Overtime Slip']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -20,10 +20,9 @@
|
||||
"section_break_12",
|
||||
"overtime_based_on",
|
||||
"maximum_overtime_hours_allowed",
|
||||
"overtime_salary_component",
|
||||
"column_break_14",
|
||||
"fetch_standard_working_hours_from_shift_type",
|
||||
"is_overtime_approval_required"
|
||||
"overtime_salary_component",
|
||||
"fetch_standard_working_hours_from_shift_type"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -112,6 +111,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval: doc.overtime_based_on == \"Attendance\"",
|
||||
"description": "If unchecked, Standard Working Hours as defined in HR Settings will be taken into consideration.",
|
||||
"fieldname": "fetch_standard_working_hours_from_shift_type",
|
||||
"fieldtype": "Check",
|
||||
@@ -128,12 +128,6 @@
|
||||
"label": "Calculate Overtime Hours Based On",
|
||||
"options": "Attendance\nTimesheet"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_overtime_approval_required",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Overtime Approval Required"
|
||||
},
|
||||
{
|
||||
"description": "Overtime payment will not be given for more than the defined hours limit.",
|
||||
"fieldname": "maximum_overtime_hours_allowed",
|
||||
@@ -145,7 +139,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-05-26 15:56:25.313007",
|
||||
"modified": "2021-06-15 13:55:44.563796",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Payroll Settings",
|
||||
|
||||
@@ -423,7 +423,7 @@
|
||||
{
|
||||
"fieldname": "net_pay_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "net pay info"
|
||||
"label": "Net Pay Info"
|
||||
},
|
||||
{
|
||||
"fieldname": "net_pay",
|
||||
@@ -631,7 +631,7 @@
|
||||
"idx": 9,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-31 22:44:09.772331",
|
||||
"modified": "2021-06-15 12:32:01.369615",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Salary Slip",
|
||||
|
||||
@@ -82,8 +82,23 @@ class SalarySlip(TransactionBase):
|
||||
if (frappe.db.get_single_value("Payroll Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry:
|
||||
self.email_salary_slip()
|
||||
|
||||
self.update_overtime_slip()
|
||||
self.update_payment_status_for_gratuity()
|
||||
|
||||
def update_overtime_slip(self):
|
||||
overtime_slips = []
|
||||
for data in self.earnings:
|
||||
if data.overtime_slips:
|
||||
overtime_slips.extend(data.overtime_slips.split(", "))
|
||||
|
||||
if self.docstatus == 1:
|
||||
for slip in overtime_slips:
|
||||
frappe.db.set_value("Overtime Slip", slip, "salary_slip", self.name)
|
||||
|
||||
if self.docstatus == 2:
|
||||
for slip in overtime_slips:
|
||||
frappe.db.set_value("Overtime Slip", slip, "salary_slip", None)
|
||||
|
||||
def update_payment_status_for_gratuity(self):
|
||||
add_salary = frappe.db.get_all("Additional Salary",
|
||||
filters = {
|
||||
@@ -101,6 +116,7 @@ class SalarySlip(TransactionBase):
|
||||
def on_cancel(self):
|
||||
self.set_status()
|
||||
self.update_status()
|
||||
self.update_overtime_slip
|
||||
self.update_payment_status_for_gratuity()
|
||||
self.cancel_loan_repayment_entry()
|
||||
|
||||
@@ -513,7 +529,7 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
def process_overtime_slips(self):
|
||||
overtime_slips = self.get_overtime_slips()
|
||||
amounts, processed_overtime_slips = self.get_overtime_amount(overtime_slips)
|
||||
amounts, processed_overtime_slips = self.get_overtime_amount(overtime_slips)
|
||||
self.add_overtime_component(amounts, processed_overtime_slips)
|
||||
|
||||
def get_overtime_slips(self):
|
||||
@@ -521,11 +537,14 @@ class SalarySlip(TransactionBase):
|
||||
'employee': self.employee,
|
||||
'posting_date': (">=", self.start_date),
|
||||
'posting_date': ("<=", self.end_date),
|
||||
'salary_slip': '',
|
||||
'docstatus': 1
|
||||
}, fields = ["name", "from_date", 'to_date'])
|
||||
|
||||
def get_overtime_amount(self, overtime_slips):
|
||||
standard_duration_amount = 0; weekends_duration_amount= 0; public_holidays_duration_amount = 0
|
||||
standard_duration_amount = 0
|
||||
weekends_duration_amount= 0
|
||||
public_holidays_duration_amount = 0
|
||||
calculated_amount = 0
|
||||
processed_overtime_slips = []
|
||||
overtime_types_details = {}
|
||||
@@ -541,7 +560,7 @@ class SalarySlip(TransactionBase):
|
||||
for detail in details:
|
||||
overtime_hours = detail.overtime_duration / 3600
|
||||
|
||||
if not detail.overtime_type in overtime_types_details:
|
||||
if detail.overtime_type not in overtime_types_details:
|
||||
details, applicable_components = self.get_overtime_type_detail(detail.overtime_type)
|
||||
overtime_types_details[detail.overtime_type] = details
|
||||
if len(applicable_components):
|
||||
@@ -551,24 +570,28 @@ class SalarySlip(TransactionBase):
|
||||
frappe.bold(detail.overtime_type)))
|
||||
|
||||
if "applicable_amount" not in overtime_types_details[detail.overtime_type].keys():
|
||||
component_amount = sum([data.default_amount for data in self.earnings \
|
||||
if data.salary_component in overtime_types_details[detail.overtime_type]["components"] \
|
||||
and not data.get('additional_salary', None)])
|
||||
component_amount = sum([data.default_amount for data in self.earnings if data.salary_component in \
|
||||
overtime_types_details[detail.overtime_type]["components"] and not data.get('additional_salary', None)])
|
||||
|
||||
overtime_types_details[detail.overtime_type]["applicable_daily_amount"] = component_amount/self.total_working_days
|
||||
|
||||
standard_working_hours = detail.standard_working_time/3600
|
||||
applicable_hourly_wages = overtime_types_details[detail.overtime_type]["applicable_daily_amount"]/standard_working_hours
|
||||
|
||||
weekend_multiplier = overtime_types_details[detail.overtime_type]['standard_multiplier']
|
||||
public_holiday_multiplier = overtime_types_details[detail.overtime_type]['standard_multiplier']
|
||||
|
||||
if overtime_types_details[detail.overtime_type]['applicable_for_weekend']:
|
||||
weekend_multiplier = overtime_types_details[detail.overtime_type]['weekend_multiplier']
|
||||
if overtime_types_details[detail.overtime_type]['applicable_for_public_holiday']:
|
||||
public_holiday_multiplier = overtime_types_details[detail.overtime_type]['public_holiday_multiplier']
|
||||
overtime_date = cstr(detail.date)
|
||||
if overtime_date in holiday_date_map.keys():
|
||||
if holiday_date_map[overtime_date].weekly_off == 1:
|
||||
calculated_amount = overtime_hours * applicable_hourly_wages *\
|
||||
overtime_types_details[detail.overtime_type]['weekend_multiplier']
|
||||
calculated_amount = overtime_hours * applicable_hourly_wages * weekend_multiplier
|
||||
weekends_duration_amount += calculated_amount
|
||||
elif holiday_date_map[overtime_date].weekly_off == 0:
|
||||
calculated_amount = overtime_hours * applicable_hourly_wages *\
|
||||
overtime_types_details[detail.overtime_type]['public_holiday_multiplier']
|
||||
calculated_amount = overtime_hours * applicable_hourly_wages * public_holiday_multiplier
|
||||
public_holidays_duration_amount += calculated_amount
|
||||
else:
|
||||
calculated_amount = overtime_hours * applicable_hourly_wages *\
|
||||
@@ -578,6 +601,7 @@ class SalarySlip(TransactionBase):
|
||||
processed_overtime_slips.append(slip.name)
|
||||
|
||||
return [weekends_duration_amount, public_holidays_duration_amount, standard_duration_amount] , processed_overtime_slips
|
||||
|
||||
def add_overtime_component(self, amounts, processed_overtime_slips):
|
||||
if len(amounts):
|
||||
overtime_salary_component = frappe.db.get_single_value("Payroll Settings", "overtime_salary_component")
|
||||
@@ -602,7 +626,11 @@ class SalarySlip(TransactionBase):
|
||||
)
|
||||
|
||||
def get_overtime_type_detail(self, name):
|
||||
detail = frappe.get_all("Overtime Type", filters = {"name": name}, fields = ["name", "standard_multiplier", "weekend_multiplier", "public_holiday_multiplier"])[0]
|
||||
detail = frappe.get_all("Overtime Type",
|
||||
filters = {"name": name},
|
||||
fields = ["name", "standard_multiplier", "weekend_multiplier", "public_holiday_multiplier",
|
||||
"applicable_for_weekend", "applicable_for_public_holiday"]
|
||||
)[0]
|
||||
components = frappe.get_all("Overtime Salary Component",
|
||||
filters = {"parent": name}, fields = ["salary_component"])
|
||||
|
||||
|
||||
12
erpnext/payroll/doctype/salary_slip/salary_slip_dashboard.py
Normal file
12
erpnext/payroll/doctype/salary_slip/salary_slip_dashboard.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'salary_slip',
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Overtime Slip']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -67,7 +67,7 @@ def set_default_settings(args):
|
||||
|
||||
payroll_settings = frappe.get_doc("Payroll Settings")
|
||||
payroll_settings.overtime_based_on = "Attendance"
|
||||
Payroll_settings.overtime_salary_component = _("Overtime Allowance")
|
||||
payroll_settings.overtime_salary_component = _("Overtime Allowance")
|
||||
payroll_settings.save()
|
||||
|
||||
def set_no_copy_fields_in_variant_settings():
|
||||
|
||||
@@ -320,7 +320,7 @@ def update_hr_defaults():
|
||||
def update_payroll_defaults():
|
||||
payroll_settings = frappe.get_doc("Payroll Settings")
|
||||
payroll_settings.overtime_based_on = "Attendance"
|
||||
Payroll_settings.overtime_salary_component = _("Overtime Allowance")
|
||||
payroll_settings.overtime_salary_component = _("Overtime Allowance")
|
||||
payroll_settings.save()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user