From 885cf10b790e97dfa824dadc89c2542efb41c85f Mon Sep 17 00:00:00 2001 From: Aysha Date: Thu, 31 Oct 2024 17:48:58 +0530 Subject: [PATCH 1/4] fix: update status of reference documents --- .../full_and_final_statement/full_and_final_statement.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py index 2a465d1ed6..5424f75e11 100644 --- a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py +++ b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py @@ -8,6 +8,9 @@ class FullandFinalStatement(Document): + def on_change(self): + update_status_of_reference_documents(self, self.status) + def before_insert(self): self.get_outstanding_statements() @@ -310,3 +313,9 @@ def update_full_and_final_statement_status(doc, method=None): fnf = frappe.get_doc("Full and Final Statement", entry.reference_name) fnf.db_set("status", status) fnf.notify_update() + + +def update_status_of_reference_documents(doc, status="Paid"): + for payable in doc.payables: + if payable.component == "Gratuity": + frappe.db.set_value("Gratuity", payable.reference_document, "status", status) From b5af146f1825975381716a70e7cb3c28cfa7a4e9 Mon Sep 17 00:00:00 2001 From: Aysha Date: Tue, 19 Nov 2024 12:35:42 +0530 Subject: [PATCH 2/4] fix: set gratuity paid_amont field --- .../full_and_final_statement.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py index 5424f75e11..482fdd4bc9 100644 --- a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py +++ b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py @@ -9,7 +9,13 @@ class FullandFinalStatement(Document): def on_change(self): - update_status_of_reference_documents(self, self.status) + for payable in self.payables: + if payable.component == "Gratuity": + frappe.db.set_value( + "Gratuity", + payable.reference_document, + {"status": self.status, "paid_amount": payable.amount}, + ) def before_insert(self): self.get_outstanding_statements() @@ -313,9 +319,3 @@ def update_full_and_final_statement_status(doc, method=None): fnf = frappe.get_doc("Full and Final Statement", entry.reference_name) fnf.db_set("status", status) fnf.notify_update() - - -def update_status_of_reference_documents(doc, status="Paid"): - for payable in doc.payables: - if payable.component == "Gratuity": - frappe.db.set_value("Gratuity", payable.reference_document, "status", status) From 2a131a27c1191b8e2451a91648fc2b681a115d23 Mon Sep 17 00:00:00 2001 From: Aysha Date: Tue, 10 Dec 2024 14:08:08 +0530 Subject: [PATCH 3/4] fix: effect of fnf statement cancellation on gratuity record --- .../full_and_final_statement.py | 11 ++++++----- hrms/payroll/doctype/gratuity/gratuity.py | 13 ++++++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py index 482fdd4bc9..a48c4860b8 100644 --- a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py +++ b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py @@ -11,11 +11,12 @@ class FullandFinalStatement(Document): def on_change(self): for payable in self.payables: if payable.component == "Gratuity": - frappe.db.set_value( - "Gratuity", - payable.reference_document, - {"status": self.status, "paid_amount": payable.amount}, - ) + gratuity = frappe.get_doc("Gratuity", payable.reference_document) + if self.status == "Paid": + amount = payable.amount if self.docstatus == 1 else 0 + gratuity.db_set("paid_amount", amount) + if self.docstatus == 2: + gratuity.set_status(update=True, cancel=True) def before_insert(self): self.get_outstanding_statements() diff --git a/hrms/payroll/doctype/gratuity/gratuity.py b/hrms/payroll/doctype/gratuity/gratuity.py index ea7d80db31..0747513276 100644 --- a/hrms/payroll/doctype/gratuity/gratuity.py +++ b/hrms/payroll/doctype/gratuity/gratuity.py @@ -37,7 +37,7 @@ def gratuity_settings(self): return self._gratuity_settings - def set_status(self, update=False): + def set_status(self, update=False, cancel=False): status = {"0": "Draft", "1": "Submitted", "2": "Cancelled"}[cstr(self.docstatus or 0)] if self.docstatus == 1: @@ -47,17 +47,24 @@ def set_status(self, update=False): else: status = "Unpaid" - if update: - self.db_set("status", status) + if update and self.status != status: + if self.status != status: + self.db_set("status", status) else: self.status = status + if cancel and self.docstatus != 2: + self.db_set("docstatus", 2) + def on_submit(self): if self.pay_via_salary_slip: self.create_additional_salary() else: self.create_gl_entries() + def on_change(self): + self.set_status(update=True) + def on_cancel(self): self.ignore_linked_doctypes = ["GL Entry"] self.create_gl_entries(cancel=True) From 5dd9e1eba72f3a2b9ff87e181f034ee6be9e0345 Mon Sep 17 00:00:00 2001 From: Aysha Date: Wed, 18 Dec 2024 13:01:31 +0530 Subject: [PATCH 4/4] chore: add gratuity test and update fnf test --- .../full_and_final_statement.py | 13 ++--- .../test_full_and_final_statement.py | 2 +- .../payroll/doctype/gratuity/test_gratuity.py | 47 +++++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py index a48c4860b8..949fbb89e7 100644 --- a/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py +++ b/hrms/hr/doctype/full_and_final_statement/full_and_final_statement.py @@ -11,12 +11,13 @@ class FullandFinalStatement(Document): def on_change(self): for payable in self.payables: if payable.component == "Gratuity": - gratuity = frappe.get_doc("Gratuity", payable.reference_document) - if self.status == "Paid": - amount = payable.amount if self.docstatus == 1 else 0 - gratuity.db_set("paid_amount", amount) - if self.docstatus == 2: - gratuity.set_status(update=True, cancel=True) + if frappe.db.exists("Gratuity", payable.reference_document): + gratuity = frappe.get_doc("Gratuity", payable.reference_document) + if self.status == "Paid": + amount = payable.amount if self.docstatus == 1 else 0 + gratuity.db_set("paid_amount", amount) + if self.docstatus == 2: + gratuity.set_status(cancel=True) def before_insert(self): self.get_outstanding_statements() diff --git a/hrms/hr/doctype/full_and_final_statement/test_full_and_final_statement.py b/hrms/hr/doctype/full_and_final_statement/test_full_and_final_statement.py index ed5cae7949..1ea84f859c 100644 --- a/hrms/hr/doctype/full_and_final_statement/test_full_and_final_statement.py +++ b/hrms/hr/doctype/full_and_final_statement/test_full_and_final_statement.py @@ -34,7 +34,7 @@ def test_check_bootstraped_data_asset_movement_and_jv_creation(self): "Leave Encashment", ] - receivable_bootstraped_component = ["Employee Advance", "Loan"] + receivable_bootstraped_component = self.fnf.get_receivable_component() # checking payables and receivables bootstraped value self.assertEqual([payable.component for payable in self.fnf.payables], payables_bootstraped_component) diff --git a/hrms/payroll/doctype/gratuity/test_gratuity.py b/hrms/payroll/doctype/gratuity/test_gratuity.py index f5da015f79..941a111e26 100644 --- a/hrms/payroll/doctype/gratuity/test_gratuity.py +++ b/hrms/payroll/doctype/gratuity/test_gratuity.py @@ -171,6 +171,52 @@ def test_gratuity_amount_consistent_irrespective_of_payment_days(self): ) self.assertEqual(gratuity.amount, 190000.0) + @set_holiday_list("Salary Slip Test Holiday List", "_Test Company") + def test_settle_gratuity_via_fnf_statement(self): + from hrms.hr.doctype.full_and_final_statement.test_full_and_final_statement import ( + create_full_and_final_statement, + ) + + create_salary_slip(self.employee) + setup_gratuity_rule("Rule Under Limited Contract (UAE)") + set_mode_of_payment_account() + + # create gratuity + gratuity = create_gratuity( + expense_account="Payment Account - _TC", mode_of_payment="Cash", employee=self.employee + ) + gratuity.reload() + + # create Full and Final Statement and add gratuity as Payables + fnf = create_full_and_final_statement(self.employee) + fnf.payables = [] + fnf.receivables = [] + fnf.append( + "payables", + { + "component": "Gratuity", + "reference_document_type": "Gratuity", + "reference_document": gratuity.name, + "amount": gratuity.amount, + "account": gratuity.payable_account, + "status": "Settled", + }, + ) + fnf.save() + fnf.create_journal_entry() + + # mark fnf as paid and submit it + fnf.status = "Paid" + fnf.save() + fnf.submit() + + gratuity.reload() + self.assertEqual(gratuity.status, "Paid") + + fnf.cancel() + gratuity.reload() + self.assertEqual(gratuity.status, "Cancelled") + def setup_gratuity_rule(name: str) -> dict: from hrms.regional.united_arab_emirates.setup import setup @@ -201,6 +247,7 @@ def create_gratuity(**args): gratuity.expense_account = args.expense_account or "Payment Account - _TC" gratuity.payable_account = args.payable_account or get_payable_account("_Test Company") gratuity.mode_of_payment = args.mode_of_payment or "Cash" + gratuity.cost_center = args.cost_center or "Main - _TC" gratuity.save() gratuity.submit()