diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 4934a0788c1..facb15f15f7 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -417,11 +417,12 @@ class JournalEntry(AccountsController): def update_journal_entry_link_on_depr_schedule(self, asset, je_row): depr_schedule = get_depr_schedule(asset.name, "Active", self.finance_book) + precision = je_row.precision("debit") for d in depr_schedule or []: if ( d.schedule_date == self.posting_date and not d.journal_entry - and d.depreciation_amount == flt(je_row.debit) + and flt(d.depreciation_amount, precision) == flt(je_row.debit, precision) ): frappe.db.set_value("Depreciation Schedule", d.name, "journal_entry", self.name) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 424bf9bac87..1b808cedcc1 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -1391,6 +1391,47 @@ class TestDepreciationBasics(AssetSetup): self.assertFalse(depr_schedule[1].journal_entry) self.assertFalse(depr_schedule[2].journal_entry) + def test_depr_schedule_link_matches_at_currency_precision(self): + """A Depreciation Schedule row whose amount carries more decimals than the + company currency (e.g. 25701.202 vs a JE debit of 25701.20) must still be + matched and stamped with the Journal Entry. Comparing at exact float + equality left the link NULL, so the scheduler treated the row as unposted + and created a duplicate Journal Entry on every run. Regression test for + JournalEntry.update_journal_entry_link_on_depr_schedule().""" + from unittest.mock import MagicMock, patch + + from erpnext.accounts.doctype.journal_entry import journal_entry as journal_entry_module + + posting_date = getdate("2021-06-01") + je = frappe.new_doc("Journal Entry") + je.name = "JE-DEPR-TEST" + je.finance_book = None + je.posting_date = posting_date + + # JE debit is stored at company currency precision (2 dp)... + je_row = MagicMock() + je_row.debit = 25701.20 + je_row.precision.return_value = 2 + + # ...while the schedule row amount carries a third decimal. + schedule_row = frappe._dict( + name="DS-ROW-1", + schedule_date=posting_date, + journal_entry=None, + depreciation_amount=25701.202, + ) + asset = frappe._dict(name="ASSET-TEST") + + with ( + patch.object(journal_entry_module, "get_depr_schedule", return_value=[schedule_row]), + patch.object(frappe.db, "set_value") as mock_set_value, + ): + je.update_journal_entry_link_on_depr_schedule(asset, je_row) + + mock_set_value.assert_called_once_with( + "Depreciation Schedule", "DS-ROW-1", "journal_entry", "JE-DEPR-TEST" + ) + def test_depr_entry_posting_when_depr_expense_account_is_an_expense_account(self): """Tests if the Depreciation Expense Account gets debited and the Accumulated Depreciation Account gets credited when the former's an Expense Account."""