fix: remove Salary Slip creation from Timesheet
- moved to HRMS app
This commit is contained in:
parent
39c30f5b01
commit
4b3fb83850
@ -8,36 +8,16 @@ import frappe
|
|||||||
from frappe.utils import add_months, add_to_date, now_datetime, nowdate
|
from frappe.utils import add_months, add_to_date, now_datetime, nowdate
|
||||||
|
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
from erpnext.payroll.doctype.salary_slip.test_salary_slip import (
|
from erpnext.projects.doctype.timesheet.timesheet import OverlapError, make_sales_invoice
|
||||||
make_deduction_salary_component,
|
|
||||||
make_earning_salary_component,
|
|
||||||
)
|
|
||||||
from erpnext.payroll.doctype.salary_structure.test_salary_structure import (
|
|
||||||
create_salary_structure_assignment,
|
|
||||||
make_salary_structure,
|
|
||||||
)
|
|
||||||
from erpnext.projects.doctype.timesheet.timesheet import (
|
|
||||||
OverlapError,
|
|
||||||
make_salary_slip,
|
|
||||||
make_sales_invoice,
|
|
||||||
)
|
|
||||||
from erpnext.setup.doctype.employee.test_employee import make_employee
|
from erpnext.setup.doctype.employee.test_employee import make_employee
|
||||||
|
|
||||||
|
|
||||||
class TestTimesheet(unittest.TestCase):
|
class TestTimesheet(unittest.TestCase):
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
make_earning_salary_component(setup=True, company_list=["_Test Company"])
|
|
||||||
make_deduction_salary_component(setup=True, company_list=["_Test Company"])
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
for dt in ["Salary Slip", "Salary Structure", "Salary Structure Assignment", "Timesheet"]:
|
frappe.db.delete("Timesheet")
|
||||||
frappe.db.sql("delete from `tab%s`" % dt)
|
|
||||||
|
|
||||||
def test_timesheet_billing_amount(self):
|
def test_timesheet_billing_amount(self):
|
||||||
emp = make_employee("test_employee_6@salary.com")
|
emp = make_employee("test_employee_6@salary.com")
|
||||||
|
|
||||||
make_salary_structure_for_timesheet(emp)
|
|
||||||
timesheet = make_timesheet(emp, simulate=True, is_billable=1)
|
timesheet = make_timesheet(emp, simulate=True, is_billable=1)
|
||||||
|
|
||||||
self.assertEqual(timesheet.total_hours, 2)
|
self.assertEqual(timesheet.total_hours, 2)
|
||||||
@ -48,8 +28,6 @@ class TestTimesheet(unittest.TestCase):
|
|||||||
|
|
||||||
def test_timesheet_billing_amount_not_billable(self):
|
def test_timesheet_billing_amount_not_billable(self):
|
||||||
emp = make_employee("test_employee_6@salary.com")
|
emp = make_employee("test_employee_6@salary.com")
|
||||||
|
|
||||||
make_salary_structure_for_timesheet(emp)
|
|
||||||
timesheet = make_timesheet(emp, simulate=True, is_billable=0)
|
timesheet = make_timesheet(emp, simulate=True, is_billable=0)
|
||||||
|
|
||||||
self.assertEqual(timesheet.total_hours, 2)
|
self.assertEqual(timesheet.total_hours, 2)
|
||||||
@ -58,28 +36,6 @@ class TestTimesheet(unittest.TestCase):
|
|||||||
self.assertEqual(timesheet.time_logs[0].billing_amount, 0)
|
self.assertEqual(timesheet.time_logs[0].billing_amount, 0)
|
||||||
self.assertEqual(timesheet.total_billable_amount, 0)
|
self.assertEqual(timesheet.total_billable_amount, 0)
|
||||||
|
|
||||||
def test_salary_slip_from_timesheet(self):
|
|
||||||
emp = make_employee("test_employee_6@salary.com", company="_Test Company")
|
|
||||||
|
|
||||||
salary_structure = make_salary_structure_for_timesheet(emp)
|
|
||||||
timesheet = make_timesheet(emp, simulate=True, is_billable=1)
|
|
||||||
salary_slip = make_salary_slip(timesheet.name)
|
|
||||||
salary_slip.submit()
|
|
||||||
|
|
||||||
self.assertEqual(salary_slip.total_working_hours, 2)
|
|
||||||
self.assertEqual(salary_slip.hour_rate, 50)
|
|
||||||
self.assertEqual(salary_slip.earnings[0].salary_component, "Timesheet Component")
|
|
||||||
self.assertEqual(salary_slip.earnings[0].amount, 100)
|
|
||||||
self.assertEqual(salary_slip.timesheets[0].time_sheet, timesheet.name)
|
|
||||||
self.assertEqual(salary_slip.timesheets[0].working_hours, 2)
|
|
||||||
|
|
||||||
timesheet = frappe.get_doc("Timesheet", timesheet.name)
|
|
||||||
self.assertEqual(timesheet.status, "Payslip")
|
|
||||||
salary_slip.cancel()
|
|
||||||
|
|
||||||
timesheet = frappe.get_doc("Timesheet", timesheet.name)
|
|
||||||
self.assertEqual(timesheet.status, "Submitted")
|
|
||||||
|
|
||||||
def test_sales_invoice_from_timesheet(self):
|
def test_sales_invoice_from_timesheet(self):
|
||||||
emp = make_employee("test_employee_6@salary.com")
|
emp = make_employee("test_employee_6@salary.com")
|
||||||
|
|
||||||
@ -204,31 +160,6 @@ class TestTimesheet(unittest.TestCase):
|
|||||||
self.assertEqual(to_time, add_to_date(from_time, hours=2, as_datetime=True))
|
self.assertEqual(to_time, add_to_date(from_time, hours=2, as_datetime=True))
|
||||||
|
|
||||||
|
|
||||||
def make_salary_structure_for_timesheet(employee, company=None):
|
|
||||||
salary_structure_name = "Timesheet Salary Structure Test"
|
|
||||||
frequency = "Monthly"
|
|
||||||
|
|
||||||
if not frappe.db.exists("Salary Component", "Timesheet Component"):
|
|
||||||
frappe.get_doc(
|
|
||||||
{"doctype": "Salary Component", "salary_component": "Timesheet Component"}
|
|
||||||
).insert()
|
|
||||||
|
|
||||||
salary_structure = make_salary_structure(
|
|
||||||
salary_structure_name, frequency, company=company, dont_submit=True
|
|
||||||
)
|
|
||||||
salary_structure.salary_component = "Timesheet Component"
|
|
||||||
salary_structure.salary_slip_based_on_timesheet = 1
|
|
||||||
salary_structure.hour_rate = 50.0
|
|
||||||
salary_structure.save()
|
|
||||||
salary_structure.submit()
|
|
||||||
|
|
||||||
if not frappe.db.get_value("Salary Structure Assignment", {"employee": employee, "docstatus": 1}):
|
|
||||||
frappe.db.set_value("Employee", employee, "date_of_joining", add_months(nowdate(), -5))
|
|
||||||
create_salary_structure_assignment(employee, salary_structure.name)
|
|
||||||
|
|
||||||
return salary_structure
|
|
||||||
|
|
||||||
|
|
||||||
def make_timesheet(
|
def make_timesheet(
|
||||||
employee,
|
employee,
|
||||||
simulate=False,
|
simulate=False,
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
frappe.ui.form.on("Timesheet", {
|
frappe.ui.form.on("Timesheet", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frappe.require("/assets/erpnext/js/projects/timer.js");
|
frappe.require("/assets/erpnext/js/projects/timer.js");
|
||||||
frm.add_fetch('employee', 'employee_name', 'employee_name');
|
|
||||||
frm.fields_dict.employee.get_query = function() {
|
frm.fields_dict.employee.get_query = function() {
|
||||||
return {
|
return {
|
||||||
filters:{
|
filters:{
|
||||||
@ -43,15 +43,15 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(frm.doc.docstatus==1) {
|
if (frm.doc.docstatus == 1) {
|
||||||
if(frm.doc.per_billed < 100 && frm.doc.total_billable_hours && frm.doc.total_billable_hours > frm.doc.total_billed_hours){
|
if (
|
||||||
frm.add_custom_button(__('Create Sales Invoice'), function() { frm.trigger("make_invoice") },
|
(frm.doc.per_billed < 100)
|
||||||
"fa fa-file-text");
|
&& (frm.doc.total_billable_hours)
|
||||||
}
|
&& (frm.doc.total_billable_hours > frm.doc.total_billed_hours)
|
||||||
|
) {
|
||||||
if(!frm.doc.salary_slip && frm.doc.employee){
|
frm.add_custom_button(__("Create Sales Invoice"), function() {
|
||||||
frm.add_custom_button(__('Create Salary Slip'), function() { frm.trigger("make_salary_slip") },
|
frm.trigger("make_invoice");
|
||||||
"fa fa-file-text");
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,13 +210,6 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
make_salary_slip: function(frm) {
|
|
||||||
frappe.model.open_mapped_doc({
|
|
||||||
method: "erpnext.projects.doctype.timesheet.timesheet.make_salary_slip",
|
|
||||||
frm: frm
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
parent_project: function(frm) {
|
parent_project: function(frm) {
|
||||||
set_project_in_timelog(frm);
|
set_project_in_timelog(frm);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
"exchange_rate",
|
"exchange_rate",
|
||||||
"sales_invoice",
|
"sales_invoice",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"salary_slip",
|
|
||||||
"status",
|
"status",
|
||||||
"parent_project",
|
"parent_project",
|
||||||
"employee_detail",
|
"employee_detail",
|
||||||
@ -85,15 +84,6 @@
|
|||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "salary_slip",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Salary Slip",
|
|
||||||
"no_copy": 1,
|
|
||||||
"options": "Salary Slip",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "Draft",
|
"default": "Draft",
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
@ -120,6 +110,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "employee",
|
"depends_on": "employee",
|
||||||
|
"fetch_from": "employee.employee_name",
|
||||||
"fieldname": "employee_name",
|
"fieldname": "employee_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
@ -320,7 +311,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-06-09 12:08:53.930200",
|
"modified": "2022-06-15 22:08:53.930200",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Timesheet",
|
"name": "Timesheet",
|
||||||
|
|||||||
@ -23,7 +23,6 @@ class OverWorkLoggedError(frappe.ValidationError):
|
|||||||
|
|
||||||
class Timesheet(Document):
|
class Timesheet(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.set_employee_name()
|
|
||||||
self.set_status()
|
self.set_status()
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
self.validate_time_logs()
|
self.validate_time_logs()
|
||||||
@ -32,10 +31,6 @@ class Timesheet(Document):
|
|||||||
self.calculate_percentage_billed()
|
self.calculate_percentage_billed()
|
||||||
self.set_dates()
|
self.set_dates()
|
||||||
|
|
||||||
def set_employee_name(self):
|
|
||||||
if self.employee and not self.employee_name:
|
|
||||||
self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
|
|
||||||
|
|
||||||
def calculate_total_amounts(self):
|
def calculate_total_amounts(self):
|
||||||
self.total_hours = 0.0
|
self.total_hours = 0.0
|
||||||
self.total_billable_hours = 0.0
|
self.total_billable_hours = 0.0
|
||||||
@ -77,10 +72,7 @@ class Timesheet(Document):
|
|||||||
if self.per_billed == 100:
|
if self.per_billed == 100:
|
||||||
self.status = "Billed"
|
self.status = "Billed"
|
||||||
|
|
||||||
if self.salary_slip:
|
if self.sales_invoice:
|
||||||
self.status = "Payslip"
|
|
||||||
|
|
||||||
if self.sales_invoice and self.salary_slip:
|
|
||||||
self.status = "Completed"
|
self.status = "Completed"
|
||||||
|
|
||||||
def set_dates(self):
|
def set_dates(self):
|
||||||
@ -403,27 +395,6 @@ def make_sales_invoice(source_name, item_code=None, customer=None, currency=None
|
|||||||
return target
|
return target
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def make_salary_slip(source_name, target_doc=None):
|
|
||||||
target = frappe.new_doc("Salary Slip")
|
|
||||||
set_missing_values(source_name, target)
|
|
||||||
target.run_method("get_emp_and_working_day_details")
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
|
|
||||||
def set_missing_values(time_sheet, target):
|
|
||||||
doc = frappe.get_doc("Timesheet", time_sheet)
|
|
||||||
target.employee = doc.employee
|
|
||||||
target.employee_name = doc.employee_name
|
|
||||||
target.salary_slip_based_on_timesheet = 1
|
|
||||||
target.start_date = doc.start_date
|
|
||||||
target.end_date = doc.end_date
|
|
||||||
target.posting_date = doc.modified
|
|
||||||
target.total_working_hours = doc.total_hours
|
|
||||||
target.append("timesheets", {"time_sheet": doc.name, "working_hours": doc.total_hours})
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_activity_cost(employee=None, activity_type=None, currency=None):
|
def get_activity_cost(employee=None, activity_type=None, currency=None):
|
||||||
base_currency = frappe.defaults.get_global_default("currency")
|
base_currency = frappe.defaults.get_global_default("currency")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user