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..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 @@ -8,6 +8,17 @@ class FullandFinalStatement(Document): + def on_change(self): + for payable in self.payables: + if payable.component == "Gratuity": + 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/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) 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()