From 700e864d901d4730cea2c0fc82f2b642b7c24acc Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 19 Apr 2022 13:24:29 +0530 Subject: [PATCH] fix: sort stock vouchers before reposting GLE --- erpnext/accounts/test/test_utils.py | 28 +++++++++++++++++++++++++++- erpnext/accounts/utils.py | 27 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/test/test_utils.py b/erpnext/accounts/test/test_utils.py index 0fe50083045..77c40bae2d9 100644 --- a/erpnext/accounts/test/test_utils.py +++ b/erpnext/accounts/test/test_utils.py @@ -1,10 +1,17 @@ import unittest +import frappe from frappe.test_runner import make_test_objects from erpnext.accounts.party import get_party_shipping_address -from erpnext.accounts.utils import get_future_stock_vouchers, get_voucherwise_gl_entries +from erpnext.accounts.utils import ( + get_future_stock_vouchers, + get_voucherwise_gl_entries, + sort_stock_vouchers_by_posting_date, +) +from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry class TestUtils(unittest.TestCase): @@ -47,6 +54,25 @@ class TestUtils(unittest.TestCase): msg="get_voucherwise_gl_entries not returning expected GLes", ) + def test_stock_voucher_sorting(self): + vouchers = [] + + item = make_item().name + + stock_entry = {"item": item, "to_warehouse": "_Test Warehouse - _TC", "qty": 1, "rate": 10} + + se1 = make_stock_entry(posting_date="2022-01-01", **stock_entry) + se2 = make_stock_entry(posting_date="2022-02-01", **stock_entry) + se3 = make_stock_entry(posting_date="2022-03-01", **stock_entry) + + for doc in (se1, se2, se3): + vouchers.append((doc.doctype, doc.name)) + + vouchers.append(("Stock Entry", "Wat")) + + sorted_vouchers = sort_stock_vouchers_by_posting_date(list(reversed(vouchers))) + self.assertEqual(sorted_vouchers, vouchers) + ADDRESS_RECORDS = [ { diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index eb09bdd962a..405922e16ef 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -3,6 +3,7 @@ from json import loads +from typing import List, Tuple import frappe import frappe.defaults @@ -1122,6 +1123,9 @@ def update_gl_entries_after( def repost_gle_for_stock_vouchers( stock_vouchers, posting_date, company=None, warehouse_account=None ): + if not stock_vouchers: + return + def _delete_gl_entries(voucher_type, voucher_no): frappe.db.sql( """delete from `tabGL Entry` @@ -1129,6 +1133,8 @@ def repost_gle_for_stock_vouchers( (voucher_type, voucher_no), ) + stock_vouchers = sort_stock_vouchers_by_posting_date(stock_vouchers) + if not warehouse_account: warehouse_account = get_warehouse_account_map(company) @@ -1149,6 +1155,27 @@ def repost_gle_for_stock_vouchers( _delete_gl_entries(voucher_type, voucher_no) +def sort_stock_vouchers_by_posting_date( + stock_vouchers: List[Tuple[str, str]] +) -> List[Tuple[str, str]]: + sle = frappe.qb.DocType("Stock Ledger Entry") + voucher_nos = [v[1] for v in stock_vouchers] + + sles = ( + frappe.qb.from_(sle) + .select(sle.voucher_type, sle.voucher_no, sle.posting_date, sle.posting_time, sle.creation) + .where((sle.is_cancelled == 0) & (sle.voucher_no.isin(voucher_nos))) + .groupby(sle.voucher_type, sle.voucher_no) + ).run(as_dict=True) + sorted_vouchers = [(sle.voucher_type, sle.voucher_no) for sle in sles] + + unknown_vouchers = set(stock_vouchers) - set(sorted_vouchers) + if unknown_vouchers: + sorted_vouchers.extend(unknown_vouchers) + + return sorted_vouchers + + def get_future_stock_vouchers( posting_date, posting_time, for_warehouses=None, for_items=None, company=None ):