From aefd36e050a63d31f411c8184689d51ccaa1c299 Mon Sep 17 00:00:00 2001 From: Nishka Gosalia Date: Wed, 31 Dec 2025 15:11:50 +0530 Subject: [PATCH] fix: task actual hours calculation correction post timesheet update after submit --- .../doctype/timesheet/test_timesheet.py | 50 +++++++++++++++++++ .../projects/doctype/timesheet/timesheet.py | 4 ++ 2 files changed, 54 insertions(+) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 046db983dc0..55d90e85c94 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -8,6 +8,7 @@ from frappe.tests import IntegrationTestCase from frappe.utils import add_to_date, now_datetime, nowdate from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.projects.doctype.task.test_task import create_task from erpnext.projects.doctype.timesheet.timesheet import OverlapError, make_sales_invoice from erpnext.setup.doctype.employee.test_employee import make_employee from erpnext.tests.utils import ERPNextTestSuite @@ -22,6 +23,55 @@ class TestTimesheet(ERPNextTestSuite): def setUp(self): frappe.db.delete("Timesheet") + def test_timesheet_post_update(self): + frappe.get_doc( + { + "doctype": "Property Setter", + "doctype_or_field": "DocField", + "doc_type": "Timesheet", + "field_name": "time_logs", + "property": "allow_on_submit", + "property_type": "Check", + "value": "1", + } + ).insert(ignore_permissions=True) + + task = create_task("Test Task 1") + + timesheet = frappe.new_doc("Timesheet") + timesheet.append( + "time_logs", + { + "task": task.name, + "from_time": now_datetime(), + "to_time": now_datetime() + datetime.timedelta(hours=1), + "company": "_Test Company", + }, + ) + + timesheet.save() + timesheet.submit() + task.reload() + self.assertEqual(task.actual_time, 1) + timesheet.append( + "time_logs", + { + "task": task.name, + "from_time": now_datetime(), + "to_time": now_datetime() + datetime.timedelta(hours=2), + "hours": 2, + }, + ) + + timesheet.save() + task.reload() + self.assertEqual(task.actual_time, 3) + + frappe.db.delete( + "Property Setter", + {"doc_type": "Timesheet", "field_name": "time_logs", "property": "allow_on_submit"}, + ) + def test_timesheet_base_amount(self): emp = make_employee("test_employee_6@salary.com") timesheet = make_timesheet(emp, simulate=True, is_billable=1) diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 57510a7e989..d9ee987c8c2 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -76,6 +76,10 @@ class Timesheet(Document): def on_discard(self): self.db_set("status", "Cancelled") + def on_update_after_submit(self): + self.validate_mandatory_fields() + self.update_task_and_project() + def calculate_hours(self): for row in self.time_logs: if row.to_time and row.from_time: