mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 17:04:47 +00:00
perf: skip delink_original_entry during cancellation when Immutable Ledger is enabled (#55130)
* perf: get payment ledger and remove update from delink when immutable ledger is enabled
* revert: changes of get_payment_ledger_entries
* perf: skip delink_original_entry during cancellation when Immutable Ledger is enabled
* test: for immutable ledger
* test: add posting_date in create_sales_invoice
* fix: link validation err with immutable ledger on
* test: update testcase of the immutable ledger
* refactor(test): simpler test for immutable invariants
---------
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 9eeccecd30)
# Conflicts:
# erpnext/accounts/general_ledger.py
This commit is contained in:
committed by
ruthra kumar
parent
498bd2fb4b
commit
8a4cb28d90
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import qb
|
from frappe import qb
|
||||||
from frappe.utils import nowdate
|
from frappe.query_builder.functions import Count, Sum
|
||||||
|
from frappe.utils import add_days, nowdate
|
||||||
|
|
||||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
||||||
@@ -90,6 +91,7 @@ class TestPaymentLedgerEntry(ERPNextTestSuite):
|
|||||||
posting_date = nowdate()
|
posting_date = nowdate()
|
||||||
|
|
||||||
sinv = create_sales_invoice(
|
sinv = create_sales_invoice(
|
||||||
|
posting_date=posting_date,
|
||||||
qty=qty,
|
qty=qty,
|
||||||
rate=rate,
|
rate=rate,
|
||||||
company=self.company,
|
company=self.company,
|
||||||
@@ -531,3 +533,82 @@ class TestPaymentLedgerEntry(ERPNextTestSuite):
|
|||||||
# with references removed, deletion should be possible
|
# with references removed, deletion should be possible
|
||||||
so.delete()
|
so.delete()
|
||||||
self.assertRaises(frappe.DoesNotExistError, frappe.get_doc, so.doctype, so.name)
|
self.assertRaises(frappe.DoesNotExistError, frappe.get_doc, so.doctype, so.name)
|
||||||
|
|
||||||
|
@ERPNextTestSuite.change_settings(
|
||||||
|
"Accounts Settings",
|
||||||
|
{"enable_immutable_ledger": 1},
|
||||||
|
)
|
||||||
|
def test_reverse_entries_on_cancel_for_immutable_ledger(self):
|
||||||
|
invoice_posting_date = add_days(nowdate(), -5)
|
||||||
|
gle = qb.DocType("GL Entry")
|
||||||
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
|
|
||||||
|
si = self.create_sales_invoice(qty=1, rate=100, posting_date=invoice_posting_date)
|
||||||
|
|
||||||
|
gles_before = (
|
||||||
|
qb.from_(gle)
|
||||||
|
.select(
|
||||||
|
Count(gle.name),
|
||||||
|
)
|
||||||
|
.where((gle.voucher_type == si.doctype) & (gle.voucher_no == si.name) & (gle.is_cancelled == 0))
|
||||||
|
.run()[0][0]
|
||||||
|
)
|
||||||
|
ples_before = (
|
||||||
|
qb.from_(ple)
|
||||||
|
.select(
|
||||||
|
Count(ple.name),
|
||||||
|
)
|
||||||
|
.where((ple.voucher_type == si.doctype) & (ple.voucher_no == si.name) & (ple.delinked.eq(0)))
|
||||||
|
.run()[0][0]
|
||||||
|
)
|
||||||
|
|
||||||
|
si.cancel()
|
||||||
|
|
||||||
|
gles_after = (
|
||||||
|
qb.from_(gle)
|
||||||
|
.select(Count(gle.account))
|
||||||
|
.where((gle.voucher_type == si.doctype) & (gle.voucher_no == si.name) & (gle.is_cancelled == 0))
|
||||||
|
.run()[0][0]
|
||||||
|
)
|
||||||
|
self.assertEqual(gles_after, gles_before * 2)
|
||||||
|
|
||||||
|
ples_after = (
|
||||||
|
qb.from_(ple)
|
||||||
|
.select(
|
||||||
|
Count(ple.name),
|
||||||
|
)
|
||||||
|
.where((ple.voucher_type == si.doctype) & (ple.voucher_no == si.name) & (ple.delinked.eq(0)))
|
||||||
|
.run()[0][0]
|
||||||
|
)
|
||||||
|
self.assertEqual(ples_after, ples_before * 2)
|
||||||
|
|
||||||
|
# assert debit/credit are reversed
|
||||||
|
gl_entries = (
|
||||||
|
qb.from_(gle)
|
||||||
|
.select(gle.account, Sum(gle.debit).as_("total_debit"), Sum(gle.credit).as_("total_credit"))
|
||||||
|
.where((gle.voucher_type == si.doctype) & (gle.voucher_no == si.name) & (gle.is_cancelled == 0))
|
||||||
|
.groupby(gle.account)
|
||||||
|
.run(as_dict=True)
|
||||||
|
)
|
||||||
|
for gl in gl_entries:
|
||||||
|
with self.subTest(gl=gl):
|
||||||
|
self.assertEqual(gl.total_debit, gl.total_credit)
|
||||||
|
|
||||||
|
# assert amounts are reversed
|
||||||
|
pl_entries = (
|
||||||
|
qb.from_(ple)
|
||||||
|
.select(ple.account, Sum(ple.amount).as_("total_amount"))
|
||||||
|
.where((ple.voucher_type == si.doctype) & (ple.voucher_no == si.name) & (ple.delinked == 0))
|
||||||
|
.groupby(ple.account)
|
||||||
|
.run(as_dict=True)
|
||||||
|
)
|
||||||
|
for pl in pl_entries:
|
||||||
|
with self.subTest(pl=pl):
|
||||||
|
self.assertEqual(pl.total_amount, 0)
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
frappe.db.exists(
|
||||||
|
"Payment Ledger Entry",
|
||||||
|
{"voucher_type": si.doctype, "voucher_no": si.name, "delinked": 1},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|||||||
@@ -431,6 +431,8 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
|
|||||||
gle.flags.adv_adj = adv_adj
|
gle.flags.adv_adj = adv_adj
|
||||||
gle.flags.update_outstanding = update_outstanding or "Yes"
|
gle.flags.update_outstanding = update_outstanding or "Yes"
|
||||||
gle.flags.notify_update = False
|
gle.flags.notify_update = False
|
||||||
|
if gle.is_cancelled or is_immutable_ledger_enabled():
|
||||||
|
gle.flags.ignore_links = True
|
||||||
gle.submit()
|
gle.submit()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -2130,8 +2130,9 @@ def create_payment_ledger_entry(
|
|||||||
ple = frappe.get_doc(entry)
|
ple = frappe.get_doc(entry)
|
||||||
|
|
||||||
if cancel:
|
if cancel:
|
||||||
delink_original_entry(ple, partial_cancel=partial_cancel)
|
if not is_immutable_ledger_enabled():
|
||||||
if is_immutable_ledger_enabled():
|
delink_original_entry(ple, partial_cancel=partial_cancel)
|
||||||
|
else:
|
||||||
ple.delinked = 0
|
ple.delinked = 0
|
||||||
ple.posting_date = frappe.form_dict.get("posting_date") or getdate()
|
ple.posting_date = frappe.form_dict.get("posting_date") or getdate()
|
||||||
|
|
||||||
@@ -2220,6 +2221,7 @@ def delink_original_entry(pl_entry, partial_cancel=False):
|
|||||||
qb.update(ple)
|
qb.update(ple)
|
||||||
.set(ple.modified, now())
|
.set(ple.modified, now())
|
||||||
.set(ple.modified_by, frappe.session.user)
|
.set(ple.modified_by, frappe.session.user)
|
||||||
|
.set(ple.delinked, True)
|
||||||
.where(
|
.where(
|
||||||
(ple.company == pl_entry.company)
|
(ple.company == pl_entry.company)
|
||||||
& (ple.account_type == pl_entry.account_type)
|
& (ple.account_type == pl_entry.account_type)
|
||||||
@@ -2236,9 +2238,6 @@ def delink_original_entry(pl_entry, partial_cancel=False):
|
|||||||
if partial_cancel:
|
if partial_cancel:
|
||||||
query = query.where(ple.voucher_detail_no == pl_entry.voucher_detail_no)
|
query = query.where(ple.voucher_detail_no == pl_entry.voucher_detail_no)
|
||||||
|
|
||||||
if not is_immutable_ledger_enabled():
|
|
||||||
query = query.set(ple.delinked, True)
|
|
||||||
|
|
||||||
query.run()
|
query.run()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user